/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "纹理节点.h"
#include "节点数据声明.h"

#include "材质纹理JIT函数绑定.h"

#include "节点/节点树.h"

#include "../插座/字符插座.h"
#include "../插座/C_数值插座.h"
#include "../插座/list/list数值插座.h"
#include "../socket_utils.h"

#include "Context/数据创建销毁.h"
#include "Context/当前默认操作数据.h"

#include <core/shader_noise.h>
#include <core/属性.h>

#include <UI/UI.h>
#include <ppl.h>


#include <opencv2/tracking.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>





//static cv::Ptr<cv::Tracker> m_跟踪器 = 0;
//static std::map<C_流视频节点*, cv::Ptr<cv::Tracker>>		g_目标跟踪器;
static std::vector<cv::Ptr<cv::Tracker>>					g_目标跟踪器;
static std::map<C_流视频节点*, cv::MultiTracker>			g_多目标跟踪器;




void f_JIT_重新加载纹理(void* nodr_ptr, int32 帧) {
	((C_外部纹理节点*)nodr_ptr)->f_更新视频纹理(帧);
}





C_二维纹理节点::C_二维纹理节点(S_设备环境& ctx) : C_节点基类(DEF_二维纹理节点) {
	f_setWName(u"二维纹理");
	m_Ctx = ctx;
	
	DEF_创建UI32插座_I(u"数量");
	DEF_创建uVec2插座_I(u"分辨率");
	
	DEF_创建纹理_1D插座_O(u"纹理", ctx);
	

	DEF_UI32插座数据(f_get输入插座(1)) = 1;
	DEF_uVec2插座数据(f_get输入插座(2)) = {1,1};
	//std::cout<<sizeof(E_节点类型)<<std::endl;
	m_纹理库 = f_alloc_StrIndexProp(S_光追后端::G纹理, u"");
	m_纹理库.m_私有 = true;

	m_GPU纹理 = f_alloc_BoolProp(nullptr, u"分配GPU纹理");
	m_GPU纹理.m_私有 = true;
	f_prop_Bool(m_GPU纹理) = false;


	m_像素位宽 = f_prop_创建图像位宽类型属性数据();
	m_像素位宽.m_私有 = true;

	m_像素通道 = f_prop_创建图像通道类型属性数据();
	m_像素通道.m_私有 = true;

}

C_二维纹理节点::~C_二维纹理节点() {
	f_prop_Release(m_纹理库);
	f_prop_Release(m_像素位宽);
	f_prop_Release(m_像素通道);
}

bool C_二维纹理节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	auto* outData = DEF_纹理插座_1D数据(f_get输出插座(1));

	E_纹理格式 格式;
	

	switch (f_prop_enum(m_像素通道)) {
		case 0: {
			switch (f_prop_enum(m_像素位宽)) {
				case 0: 格式 = E_纹理格式::e_tf_R8U_归一化; break;
				case 1: 格式 = E_纹理格式::e_tf_R16; break;
				case 2: 格式 = E_纹理格式::e_tf_R32; break;
			}
			break;
		}
		case 1: {
			switch (f_prop_enum(m_像素位宽)) {
				case 0: 格式 = E_纹理格式::e_tf_RGB8U_归一化; break;
				case 1: 格式 = E_纹理格式::e_tf_RGB16; break;
				case 2: 格式 = E_纹理格式::e_tf_RGB32; break;
			}
			break;
		}
		case 2: {
			switch (f_prop_enum(m_像素位宽)) {
				case 0: 格式 = E_纹理格式::e_tf_RGBA8U_归一化; break;
				case 1: 格式 = E_纹理格式::e_tf_RGBA16; break;
				case 2: 格式 = E_纹理格式::e_tf_RGBA32; break;
			}
			break;
		}
		default:
			break;
	}

	uint32 num = DEF_UI32插座数据(f_get输入插座(1));
	uint32 已有数量 = outData->count;
	for (uint32 i = num; i < 已有数量; ++i) {
		f_scene_销毁纹理(f_NodeCtx_get默认场景(), outData->ptr_userData[i], E_纹理分组类型::e_2D纹理);
	}
	f_core_array_resize((S_Array*)outData, num);

	uvec2 分辨率 = DEF_uVec2插座数据(f_get输入插座(2));
	分辨率 = vec_Max(分辨率, {1,1});
	for (uint32 i = 已有数量; i < num; ++i) {
		outData->ptr_userData[i] = f_tex_创建图像纹理(m_Ctx, { 分辨率.x, 分辨率.y, 1 }, 格式, E_纹理维度类型::e_2D);

		f_scene_创建纹理(f_NodeCtx_get默认场景(), m_Ctx, u"预创建纹理", E_纹理分组类型::e_2D纹理, outData->ptr_userData[i]);
	}

	for (uint32 i = 0; i < num; ++i) {
		f_scene_修改纹理(f_NodeCtx_get默认场景(), outData->ptr_userData[i], _uVec3(分辨率), E_纹理分组类型::e_2D纹理);
	}

	return false;
}

void C_二维纹理节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_纹理库, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_像素位宽, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_像素通道, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_二维纹理节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_纹理库, 块);
	f_prop_Save(m_像素位宽, 块);
	f_prop_Save(m_像素通道, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建纹理节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_二维纹理节点(ctx);
}

C_节点基类* f_node_加载纹理节点(S_设备环境& ctx, FILE* f) {
	C_二维纹理节点* node = new C_二维纹理节点(ctx);
	return node;
}

void f_node_保存纹理节点(C_节点基类* n, FILE* f) {
	C_二维纹理节点* node = dynamic_cast<C_二维纹理节点*>(n);
}





C_外部纹理节点::C_外部纹理节点(S_设备环境& ctx) : C_节点基类(DEF_外部纹理节点, E_节点类型::e_节点Type_纹理) {
	f_setWName(u"外部纹理");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建路径插座_I(u"路径");
	DEF_创建I32插座_I(u"帧");

	DEF_创建纹理插座_O(u"纹理", m_Ctx);

	auto m_Tex = f_scene_创建纹理(f_NodeCtx_get默认场景(), m_Ctx, f_getWName(), E_纹理分组类型::e_2D纹理);
	f_get输出插座(1)->f_setData(m_Tex);


	m_序列 = f_alloc_BoolProp(nullptr, u"序列");
	m_序列.m_私有 = true;
	f_prop_Bool(m_序列) = false;

	m_序列偏移 = f_alloc_I32Prop(nullptr, u"序列偏移");
	m_序列偏移.m_私有 = true;
	f_prop_I32(m_序列偏移) = 0;

	m_投影方式 = f_alloc_EnumProp(nullptr, { {u"平面", u"平面"}, {u"方体", u"立体线框"}, {u"球体", u"球体"}, {u"圆柱", u"圆柱"} }, u"序列偏移");
	m_投影方式.m_私有 = true;
	f_prop_enum(m_投影方式) = 0;


	m_GPU纹理 = f_alloc_BoolProp(nullptr, u"分配GPU纹理");
	m_GPU纹理.m_私有 = true;
	f_prop_Bool(m_GPU纹理) = true;

	m_横向反转 = f_alloc_BoolProp(nullptr, u"分配GPU纹理");
	m_横向反转.m_私有 = true;
	f_prop_Bool(m_横向反转) = false;
	m_纵向反转 = f_alloc_BoolProp(nullptr, u"分配GPU纹理");
	m_纵向反转.m_私有 = true;
	f_prop_Bool(m_纵向反转) = true;


	m_资源集类型 = f_alloc_EnumProp(nullptr, {
		{u"图像文件"}, 
		{u"视频文件"},
	}, u"资源集类型");
	m_资源集类型.m_私有 = true;

	m_文件数组 = f_alloc_BoolProp(nullptr, u"文件数组");
	m_文件数组.m_私有 = true;
	f_prop_Bool(m_文件数组) = false;

	m_文件夹下所有文件 = f_alloc_BoolProp(nullptr, u"文件夹下所有文件");
	m_文件夹下所有文件.m_私有 = true;
	f_prop_Bool(m_文件夹下所有文件) = true;

	m_图像预设后缀 = f_alloc_Prop多按钮(nullptr, *S_节点数据::g_图像文件后缀, u"图像类型");
	m_图像预设后缀.m_私有 = true;
	f_prop_UI32位域枚举(m_图像预设后缀) = 0xffffffff;

	m_视频预设后缀 = f_alloc_Prop多按钮(nullptr, *S_节点数据::g_视频文件后缀, u"视频类型");
	m_视频预设后缀.m_私有 = true;
	f_prop_UI32位域枚举(m_视频预设后缀) = 0xffffffff;

	m_开启过滤 = f_alloc_BoolProp(nullptr, u"开启过滤");
	m_开启过滤.m_私有 = true;

	m_过滤名称 = f_alloc_StrProp(nullptr, u"过滤名称");
	m_过滤名称.m_私有 = true;



	f_构建代码_分配渲染器GPU属性变量(m_投影方式);
	//m_Tex->m_纹理坐标计算类型 = m_投影方式.m_GPU缓存[0].m_Mem.m_偏移;


	m_自定义更新方式 = true;
	
}

C_外部纹理节点::~C_外部纹理节点() {
	f_构建代码_释放渲染器GPU属性变量(m_投影方式);

	f_prop_Release(m_序列);
	f_prop_Release(m_序列偏移);
	f_prop_Release(m_横向反转);
	f_prop_Release(m_纵向反转);

	f_prop_Release(m_资源集类型);
	f_prop_Release(m_文件数组);
	f_prop_Release(m_图像预设后缀);
	f_prop_Release(m_视频预设后缀);
	f_prop_Release(m_开启过滤);
	f_prop_Release(m_过滤名称);


	for (auto& e : m_视频环境) {
		f_scene_销毁纹理(f_NodeCtx_get默认场景(), e.second.m_纹理, E_纹理分组类型::e_2D纹理);
		//f_释放视频(e.second);
	}
}

void C_外部纹理节点::f_释放视频(S_AV_Ctex& ctx) {
	if (ctx.m_帧) av_frame_free(&ctx.m_帧);
	//if (ctx.m_输出帧) av_frame_free(&m_输出帧);
	if (ctx.m_编码环境) avcodec_close(ctx.m_编码环境);
	if (ctx.m_格式环境) avformat_close_input(&ctx.m_格式环境);
	if (ctx.m_转换格式环境) sws_freeContext(ctx.m_转换格式环境);
	ctx.m_VideoStreamIndex = -1;
}

bool C_外部纹理节点::f_加载视频(S_AV_Ctex& ctx) {
	f_释放视频(ctx);

	int32 err = avformat_open_input(&ctx.m_格式环境, ctx.m_文件路径.c_str(), nullptr, nullptr);
	if(err != 0) return false;

	avformat_find_stream_info(ctx.m_格式环境, nullptr);

	ctx.m_VideoStreamIndex = av_find_best_stream(ctx.m_格式环境, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
	

	AVCodecParameters* 编码器参数 = ctx.m_格式环境->streams[ctx.m_VideoStreamIndex]->codecpar;
	AVCodec* 视频编码器 = avcodec_find_decoder(编码器参数->codec_id);
	ctx.m_编码环境 = avcodec_alloc_context3(视频编码器);

	ctx.m_帧 = av_frame_alloc();
	//ctx.m_输出帧 = av_frame_alloc();

	avcodec_parameters_to_context(ctx.m_编码环境, 编码器参数);
	avcodec_open2(ctx.m_编码环境, 视频编码器, nullptr);

	return true;
}

void C_外部纹理节点::f_读取视频帧(S_AV_Ctex& ctx, int32 帧) {
	if(ctx.m_格式环境 == nullptr) return;

	AVStream* stream = ctx.m_格式环境->streams[ctx.m_VideoStreamIndex];

	int64 持续时间 = ctx.m_格式环境->streams[ctx.m_VideoStreamIndex]->duration;
	AVRational 时间基准 = ctx.m_格式环境->streams[ctx.m_VideoStreamIndex]->time_base;
	//int64_t timestamp = 帧 * 持续时间 / av_q2d(时间基准);
	float32 帧率 = av_q2d(ctx.m_格式环境->streams[ctx.m_VideoStreamIndex]->avg_frame_rate);

	int64 帧数量 = 持续时间 * av_q2d(ctx.m_格式环境->streams[ctx.m_VideoStreamIndex]->r_frame_rate);
	int64 目标帧 = (帧 > 帧数量) ? 帧数量 : 帧;
	AVRational timeBase = stream->time_base;
	

	AVRational a = {1, AV_TIME_BASE};
	int64_t timestamp = av_rescale_q(float32(帧) / 帧率 * AV_TIME_BASE, { 1, AV_TIME_BASE }, timeBase);
	std::cout<<"timestamp = " << timestamp << " = " << 帧 << std::endl;
	//return;
	int32 err = av_seek_frame(ctx.m_格式环境, ctx.m_VideoStreamIndex, timestamp, AVSEEK_FLAG_BACKWARD);

	

	uvec3 新大小{1,1,1};
	//纹理->m_格式 = E_纹理格式::e_tf_RGB8U_U;

	AVPacket packet;
	while (av_read_frame(ctx.m_格式环境, &packet) >= 0) {
		if (packet.stream_index == ctx.m_VideoStreamIndex) {
			avcodec_send_packet(ctx.m_编码环境, &packet);
			
			//m_帧 = av_frame_alloc();
			auto arf = avcodec_receive_frame(ctx.m_编码环境, ctx.m_帧);
			
			if (arf == 0) {
				if(ctx.m_帧->pts < timestamp) {
					av_packet_unref(&packet);
					continue;
				}

				//if (m_帧->pts == timestamp) {
				ctx.m_转换格式环境 = sws_getContext(ctx.m_编码环境->width, ctx.m_编码环境->height, ctx.m_编码环境->pix_fmt,
					ctx.m_编码环境->width, ctx.m_编码环境->height, AV_PIX_FMT_RGBA, SWS_BILINEAR, nullptr, nullptr, nullptr);

				新大小.x = ctx.m_帧->width;
				新大小.y = ctx.m_帧->height;

				if (ctx.m_纹理->m_像素) {
					ctx.m_纹理->m_像素 = realloc(ctx.m_纹理->m_像素, 新大小.x * 新大小.y * sizeof(S_RGBA8UI));
				}
				else {
					ctx.m_纹理->m_像素 = calloc(新大小.x * 新大小.y, sizeof(S_RGBA8UI));
				}
				S_RGBA8UI* data = (S_RGBA8UI*)(ctx.m_纹理->m_像素);

				S_RGBA8UI* rgbBuffer = new S_RGBA8UI[新大小.x * 新大小.y];
				
				int dstLinesize[4];
				dstLinesize[0] = ctx.m_帧->width * 4;
				dstLinesize[1] = 0;
				dstLinesize[2] = 0;
				dstLinesize[3] = 0;
				//sws_scale(m_转换格式环境, m_帧->data, m_帧->linesize, 0, m_帧->height, (uint8**)&rgbBuffer, dstLinesize);
				sws_scale(ctx.m_转换格式环境, ctx.m_帧->data, ctx.m_帧->linesize, 0, ctx.m_帧->height, (uint8**)&data, dstLinesize);

				delete[] rgbBuffer;
				//break;
				//}
			}
			else if (arf == AVERROR_EOF) {
				std::cout << "err 0" << std::endl;
				break;
			}
			else {
				std::cout << "err 1" << std::endl;
			}

			//av_frame_free(&m_帧);
			av_packet_unref(&packet);
			break;
		}
	}

	f_scene_往渲染器里添加纹理({ ctx.m_文件路径, ctx.m_纹理, f_NodeCtx_get默认场景(), 新大小 }, false);
}

void C_外部纹理节点::f_更新视频纹理(int32 帧) {
	if (f_更新是否跳过()) {
		return;
	}

	auto& 路径 = *DEF_路径插座数据(f_get输入插座(1), 0);
	
	std::vector<std::u16string> 过滤后缀;
	bool 加载视频 = false;
	//if (f_prop_Bool(m_开启过滤)) {	
	//}
	switch (f_prop_enum(m_资源集类型)) {
		case 0: {
			过滤后缀 = f_prop_EnumItem_Names(m_图像预设后缀);
			break;
		}
		case 1: {
			过滤后缀 = f_prop_EnumItem_Names(m_视频预设后缀);
			加载视频 = true;
			break;
		}
	}
	if (过滤后缀.empty()) return;

	auto 文件夹路径 = f_file_get路径(路径);

	std::string path;
	if (f_prop_Bool(m_文件数组)) {
		
		S_目录文件包 目录文件;
		if (f_prop_Bool(m_文件夹下所有文件)) {
			f_file_get目录下所有文件名(文件夹路径.u16string(), 目录文件, 过滤后缀);
		}
		else {
			std::cout<<"自定义文件名称组  施工中..................."<<std::endl;
		}

		auto* 纹理 = DEF_纹理插座_1D数据(f_get输出插座(1));

		for (auto& e : m_视频环境) {
			e.second.m_已加载 = false;
		}

		for (auto& e : 目录文件.文件) {
			std::string 文件名称 = (文件夹路径 / e).generic_string();

			if (m_视频环境.find(文件名称) == m_视频环境.end()) {
				
				m_视频环境[文件名称] = S_AV_Ctex();
				S_AV_Ctex& ctx = m_视频环境[文件名称];

				ctx.m_文件路径 = 文件名称;
				//ctx.m_纹理 = f_tex_创建图像纹理(m_Ctx, { 8,8,1 }, E_纹理格式::e_tf_RGBA8U_U, E_纹理维度类型::e_2D);
				ctx.m_纹理 = f_scene_创建纹理(f_NodeCtx_get默认场景(), m_Ctx, f_getWName(), E_纹理分组类型::e_2D纹理);
				m_视频环境[文件名称] = ctx;

				if (f_加载视频(ctx)) {
					m_视频环境[文件名称].m_已加载 = true;
				}
			}

			S_AV_Ctex& ctx = m_视频环境[文件名称];
			if (加载视频) {
				
			}
			else {
				//f_scene_往渲染器里添加纹理({ ctx.m_文件路径, ctx.m_纹理, f_NodeCtx_get默认场景() }, true);
				
			}
			m_视频环境[文件名称].m_已加载 = true;
		}

		for (auto it = m_视频环境.begin(); it != m_视频环境.end(); ) {
			if (it->second.m_已加载 == false) {
				f_scene_销毁纹理(f_NodeCtx_get默认场景(), it->second.m_纹理, E_纹理分组类型::e_2D纹理);
				it = m_视频环境.erase(it);
			}
			else {
				++it;
			}
		}

		for (auto& e : m_视频环境) {
			f_读取视频帧(e.second, 帧);
		}
	}
	else {
		auto 文件路径 = 路径.string();
		auto* 纹理 = DEF_纹理插座数据(f_get输出插座(1));

		S_AV_Ctex* ctx;

		if (f_file_文件是否存在(文件路径)) {
			if (加载视频) {
				加载视频 = f_file_文件过滤(路径.u16string(), f_prop_EnumItem_Names(m_视频预设后缀));

				if (加载视频) {

					if (m_视频环境.find(文件路径) == m_视频环境.end()) {
						m_视频环境.clear();
						m_视频环境[文件路径] = S_AV_Ctex();
						ctx = &m_视频环境[文件路径];

						ctx->m_纹理 = 纹理;
						ctx->m_文件路径 = 路径.string();

						f_加载视频(*ctx);
					}
					else {
						ctx = &m_视频环境[文件路径];
					}

					f_读取视频帧(m_视频环境[文件路径], 帧);
				}
			}
			else {
				加载视频 = f_file_文件过滤(路径.u16string(), f_prop_EnumItem_Names(m_图像预设后缀));

				if (加载视频) {
					if (m_视频环境.find(文件路径) == m_视频环境.end()) {
						m_视频环境[文件路径] = S_AV_Ctex();
						ctx = &m_视频环境[文件路径];

						ctx->m_纹理 = 纹理;
						ctx->m_文件路径 = 路径.string();

						f_scene_往渲染器里添加纹理({ 文件路径, 纹理, f_NodeCtx_get默认场景() }, true);
					}
				}
			}
		}
	}


	//if (m_以加载文件记录 != 路径) {
	//	m_以加载文件记录 = 路径.string();
	//
	//	//if (路径.extension().wstring() == L".mp4") {
	//	//	f_读取视频(路径);
	//	//	f_读取视频帧(帧, 纹理);
	//	//}
	//	//else {
	//	//	f_scene_往渲染器里添加纹理({ m_以加载文件记录, 纹理, f_NodeCtx_get默认场景() }, true);
	//	//}
	//
	//	switch (f_prop_enum(m_资源集类型)) {
	//		case 0: {
	//			f_scene_往渲染器里添加纹理({ m_以加载文件记录, 纹理, f_NodeCtx_get默认场景() }, true);
	//			break;
	//		}
	//		case 1: {
	//			f_加载视频(路径);
	//			//f_读取视频帧(帧, 纹理);
	//			break;
	//		}
	//	}
	//}
	////else {
	////	if (路径.extension().wstring() == L".mp4") {
	////		f_读取视频帧(帧, 纹理);
	////	}
	////	
	////}
	//
	//switch (f_prop_enum(m_资源集类型)) {
	//	case 1: {
	//		f_读取视频帧(帧, 纹理);
	//		break;
	//	}
	//}
	
}

bool C_外部纹理节点::f_update() {
	if (f_更新是否跳过()) {
		return false;
	}

	auto 帧 = DEF_I32插座数据(f_get输入插座(2), 0);

	void* outData = nullptr;
	if (f_prop_Bool(m_文件数组)) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_纹理_1D);
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_纹理);
	}

	f_更新视频纹理(帧);


	if (f_prop_Bool(m_文件数组)) {
		S_TexArray* ts = DEF_纹理插座_1D数据(f_get输出插座(1));
		f_core_array_resize((S_Array*)ts, m_视频环境.size());

		uint32 offset = 0;
		for (auto& e : m_视频环境) {
			ts->ptr_userData[offset] = e.second.m_纹理;
			++offset;
		}
	}
	else {
		if (m_视频环境.size()) {
			f_get输出插座(1)->f_setData(m_视频环境.begin()->second.m_纹理);
		}
		else {
			f_get输出插座(1)->f_setData((void*)nullptr);
		}
	}

	
	return false;
}

std::string C_外部纹理节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	auto rt = f_getThis节点树();
	
	auto* socket2 = f_get输入插座(2);
	auto 帧 = DEF_I32插座数据(socket2, 0);

	
	if (f_prop_Bool(m_GPU纹理)) {
		
		std::string name;
		switch (rt->m_树类型) {
			case E_节点树类型::e_type_着色节点树: {
				f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_纹理);
				f_更新视频纹理(帧);

				auto* 纹理 = DEF_纹理插座数据(f_get输出插座(1), 0);

				name = f_str_汉字字符串转拼音(f_getWName());
				m_Code += "uint " + name + " = " + f_整数值转字符串(纹理->m_TexID) + ";\n";

				f_get输出插座(1)->f_setCode(name);
				break;
			}
			case E_节点树类型::e_type_材质节点树: {
				if (f_prop_Bool(m_文件数组)) {
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_纹理_1D);
				}
				else {
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_纹理);
				}
				f_更新视频纹理(帧);

				m_Code += socket2->f_构建变量代码(0);
				m_Code += DEF_S(f_JIT_重新加载纹理)"((void*)" + DEF_指针转字符串(this) + ", " + socket2->f_getCode(0) + ");\n";

				name = f_get输出插座(1)->f_构建变量代码(0);
				break;
			}
			default:
				break;
		}
	}
	else {
		//f_tex_从文件填充纹理()
	}
	
	if (f_prop_Bool(m_文件数组)) {
		S_TexArray* ts = DEF_纹理插座_1D数据(f_get输出插座(1));
		f_core_array_resize((S_Array*)ts, m_视频环境.size());

		uint32 offset = 0;
		for (auto& e : m_视频环境) {
			ts->ptr_userData[offset] = e.second.m_纹理;
			++offset;
		}
	}
	else {
		if (m_视频环境.size()) {
			f_get输出插座(1)->f_setData(m_视频环境.begin()->second.m_纹理);
		}
		else {
			f_get输出插座(1)->f_setData((void*)nullptr);
		}
	}


	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_外部纹理节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_16, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_序列, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_序列偏移, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_投影方式, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_GPU纹理, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_纵向反转, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_横向反转, 下一次读取数据指针);

			下一次读取数据指针 = f_prop_Load(m_资源集类型, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_文件数组, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_文件夹下所有文件, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_图像预设后缀, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_视频预设后缀, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_开启过滤, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_过滤名称, 下一次读取数据指针);

		}
		else if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_8, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_序列, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_序列偏移, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_投影方式, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_GPU纹理, 下一次读取数据指针);
		}
		else if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_7, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_序列, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_序列偏移, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_投影方式, 下一次读取数据指针);
		}
		else if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_低版本号_7)) {
			下一次读取数据指针 = f_prop_Load(m_序列, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_序列偏移, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_投影方式, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_外部纹理节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_序列, 块);
	f_prop_Save(m_序列偏移, 块);
	f_prop_Save(m_投影方式, 块);
	f_prop_Save(m_GPU纹理, 块);
	f_prop_Save(m_纵向反转, 块);
	f_prop_Save(m_横向反转, 块);

	f_prop_Save(m_资源集类型, 块);
	f_prop_Save(m_文件数组, 块);
	f_prop_Save(m_文件夹下所有文件, 块);
	f_prop_Save(m_图像预设后缀, 块);
	f_prop_Save(m_视频预设后缀, 块);
	f_prop_Save(m_开启过滤, 块);
	f_prop_Save(m_过滤名称, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建外部纹理节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_外部纹理节点(ctx);
}

C_节点基类* f_node_加载外部纹理节点(S_设备环境& ctx, FILE* f) {
	C_外部纹理节点* node = new C_外部纹理节点(ctx);
	return node;
}

void f_node_保存外部纹理节点(C_节点基类* n, FILE* f) {
	C_外部纹理节点* node = dynamic_cast<C_外部纹理节点*>(n);
}






C_外部纹理集节点::C_外部纹理集节点(S_设备环境& ctx) : C_节点基类(DEF_外部纹理集节点, E_节点类型::e_节点Type_纹理) {
	f_setWName(u"外部纹理集");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建路径插座_I(u"路径");
	DEF_创建纹理_1D插座_O(u"纹理", m_Ctx);

	//m_Tex = f_scene_创建纹理(f_NodeCtx_get默认场景(), m_Ctx, m_Name);
	//f_get输出插座(1)->f_setData(m_Tex);


	m_全部加载 = f_alloc_BoolProp(nullptr, u"全部加载");
	m_全部加载.m_私有 = true;
	f_prop_Bool(m_全部加载) = true;

	m_过滤名称 = f_alloc_StrProp(nullptr, u"名称");
	m_过滤名称.m_私有 = true;
	//f_prop_I32(m_序列偏移) = 0;

	m_投影方式 = f_alloc_EnumProp(nullptr, { {u"平面", u"平面"}, {u"方体", u"立体线框"}, {u"球体", u"球体"}, {u"圆柱", u"圆柱"} }, u"序列偏移");
	m_投影方式.m_私有 = true;
	f_prop_enum(m_投影方式) = 0;


	f_构建代码_分配渲染器GPU属性变量(m_投影方式);
	//m_Tex->m_纹理坐标计算类型 = m_投影方式.m_GPU缓存[0].m_Mem.m_偏移;
}

C_外部纹理集节点::~C_外部纹理集节点() {
	f_构建代码_释放渲染器GPU属性变量(m_投影方式);

	f_prop_Release(m_全部加载);
	f_prop_Release(m_过滤名称);

	auto* 纹理 = DEF_纹理插座_1D数据(f_get输出插座(1), 0);
	f_node_销毁纹理组(纹理);
}

void C_外部纹理集节点::f_加载纹理() {
	auto& 路径 = *DEF_路径插座数据(f_get输入插座(1), 0);
	auto* 纹理 = DEF_纹理插座_1D数据(f_get输出插座(1), 0);


	if (m_以加载文件记录 != 路径) {
		m_以加载文件记录 = 路径.string();
		std::string 拼接路径 = f_nodeCtx_相对路径补全(m_以加载文件记录);


		S_目录文件包 目录文件;
		f_file_get目录下所有文件名(拼接路径, 目录文件, S_引擎配置::g_支持的图像格式);

		uint32 num = 目录文件.文件.size();
		
		f_node_创建纹理组(纹理, num, m_Ctx);
		for (uint32 i = 0; i < num; ++i) {
			auto 路径 = 拼接路径 + "/" + f_str_u16_to_u8(目录文件.文件[i]);
			f_scene_往渲染器里添加纹理({ 路径, 纹理->ptr_userData[i], f_NodeCtx_get默认场景() });
		}
	}
}

bool C_外部纹理集节点::f_update() {
	auto& 路径 = *DEF_路径插座数据(f_get输入插座(1), 0);
	f_加载纹理();

	return false;
}

std::string C_外部纹理集节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";


	f_加载纹理();


	std::string name;

	auto rt = f_getThis节点树();
	switch (rt->m_树类型) {
	case E_节点树类型::e_type_着色节点树: {
		name = f_str_汉字字符串转拼音(f_getWName());
		//m_Code += "vec4 " + name + " = texture(Ts[nonuniformEXT(" + f_整数值转字符串(纹理->m_ID) + ")], );\n";
		//m_Code += "uint " + name + " = " + f_整数值转字符串(0) + ";\n";
		//m_Code += "uint " + name + " = " + f_整数值转字符串(纹理->m_TexID) + ";\n";

		break;
	}
	case E_节点树类型::e_type_材质节点树: {
		name = f_getName();
		//m_Code += "uint " + name + " = " + f_整数值转字符串(纹理->m_TexID) + ";\n";
		break;
	}
	default:
		break;
	}

	f_get输出插座(1)->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_外部纹理集节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_6, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_全部加载, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_过滤名称, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_投影方式, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_外部纹理集节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_全部加载, 块);
	f_prop_Save(m_过滤名称, 块);
	f_prop_Save(m_投影方式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建外部纹理集节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_外部纹理集节点(ctx);
}

C_节点基类* f_node_加载外部纹理集节点(S_设备环境& ctx, FILE* f) {
	C_外部纹理集节点* node = new C_外部纹理集节点(ctx);
	return node;
}

void f_node_保存外部纹理集节点(C_节点基类* n, FILE* f) {
	C_外部纹理集节点* node = dynamic_cast<C_外部纹理集节点*>(n);
}



C_加载纹理节点::C_加载纹理节点(S_设备环境& ctx) : C_节点基类(DEF_加载纹理节点, E_节点类型::e_节点Type_纹理) {
	f_setWName(u"加载纹理");
	m_Ctx = ctx;

	DEF_创建纹理插座_O(u"纹理", m_Ctx);
	DEF_创建字符串插座_I(u"路径");

	m_GPU纹理 = f_alloc_BoolProp(nullptr, u"分配GPU纹理");
	m_GPU纹理.m_私有 = true;
	f_prop_Bool(m_GPU纹理) = false;

	f_prop_创建图像通道类型属性数据();

	m_自定义更新方式 = true;
}

C_加载纹理节点::~C_加载纹理节点() {
	f_prop_Release(m_GPU纹理);
}

bool C_加载纹理节点::f_update() {
	f_tex_从文件加载纹理(DEF_纹理插座数据(f_get输出插座(1)), DEF_字符串插座数据(f_get输入插座(1)));
	if (f_prop_Bool(m_GPU纹理)) {
		
	}
	else {
		//f_tex_创建图像纹理(m_Ctx, { 1, 1, 1 }, E_纹理格式::e_tf_RGBA8U_U, E_纹理维度类型::e_2D);
		//f_tex_从文件填充纹理(纹理, 路径, 4);
	}
	return false;
}

std::string C_加载纹理节点::DEF_节点编译函数 {
	m_Code = "";
	m_ReleaseCode = "";
	auto name = f_getName();

	auto socket1 = f_get输入插座(1);

	m_Code += DEF_S(S_纹理*)" " + name + ";\n";
	m_Code += name + " = " + DEF_S(f_tex_创建图像)"(*(S_设备环境*)" + DEF_指针转字符串(&m_Ctx) + ", {2,2,1}" + ", E_纹理格式::e_tf_RGBA8U_归一化, E_纹理维度类型::e_2D);\n";

	m_Code += "{\n";
	m_Code += socket1->f_构建变量代码(0);

	//if (f_prop_Bool(m_更新方式属性)) {
	//	m_Code += "if(";
	//	m_Code += DEF_S(*DEF_全局变量_g_执行状态离线_)"){\n";
	//	m_Code += DEF_S(f_tex_从文件加载纹理)"(" + name + ", " + socket1->f_getCode(0) + ", 4);\n";
	//	m_Code += "}\n";
	//}
	//else {
	//	m_Code += DEF_S(f_tex_从文件加载纹理)"(" + name + ", " + socket1->f_getCode(0) + ", 4);\n";
	//}
	
	m_Code += DEF_S(f_tex_从文件加载纹理)"(" + name + ", " + socket1->f_getCode(0) + ", 4);\n";
	m_Code += "}\n";

	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		
		m_区域父节点->m_ReleaseCode.insert(0, DEF_S(f_tex_销毁纹理)"(" + name + ");\n");
		return "";
	}
	释放 += DEF_S(f_tex_销毁纹理)"(" + name + ");\n";
	return m_Code;
}

void C_加载纹理节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_6, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_GPU纹理, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_加载纹理节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_GPU纹理, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建加载纹理节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_加载纹理节点(ctx);
}

C_节点基类* f_node_加载加载纹理节点(S_设备环境& ctx, FILE* f) {
	C_加载纹理节点* node = new C_加载纹理节点(ctx);
	return node;
}

void f_node_保存加载纹理节点(C_节点基类* n, FILE* f) {
	C_加载纹理节点* node = dynamic_cast<C_加载纹理节点*>(n);
}



C_从文件填充纹理节点::C_从文件填充纹理节点(S_设备环境& ctx) : C_节点基类(DEF_从文件填充纹理节点, E_节点类型::e_节点Type_纹理) {
	f_setWName(u"从文件填充纹理");
	m_Ctx = ctx;

	DEF_创建纹理_1D插座_I(u"纹理", m_Ctx);
	DEF_创建字符串数组插座_I(u"路径");

	DEF_创建纹理_1D插座_O(u"纹理", m_Ctx);


	m_填充方式 = f_alloc_EnumProp(nullptr, {
		{u"异步加载"}
	}, u"填充方式");
	m_填充方式.m_私有 = true;

	m_自定义更新方式 = true;
}

C_从文件填充纹理节点::~C_从文件填充纹理节点() {
	f_prop_Release(m_填充方式);
}

bool C_从文件填充纹理节点::f_update() {
	auto 纹理 = DEF_纹理插座_1D数据(f_get输入插座(1));
	auto 路径 = DEF_字符串数组插座数据(f_get输入插座(2));

	if(!路径->count) return false;


	if (f_更新是否跳过()) {
		return false;
	}

	uint32 num = DEF_Max(纹理->count, 路径->count);
	bool 纹理多例 = 纹理->count >= num;
	bool 路径多例 = 路径->count >= num;

	for (int32 i = 0; i < num; ++i) {
		std::string path = f_str_u16_to_u8(f_prop_LineStr(路径多例 ? *路径->ptr_userData[i] : *路径->ptr_userData[0]));
		std::string 拼接路径 = f_nodeCtx_相对路径补全(path);

		f_scene_往渲染器里添加纹理({ 拼接路径, 纹理->ptr_userData[i], f_NodeCtx_get默认场景() }, true);
		//f_tex_从文件填充纹理(纹理->ptr_userData[i], 拼接路径);
	}

	f_get输出插座(1)->f_setData(纹理);

	return false;
}

void C_从文件填充纹理节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_填充方式, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_从文件填充纹理节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_填充方式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建从文件填充纹理节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_从文件填充纹理节点(ctx);
}

C_节点基类* f_node_加载从文件填充纹理节点(S_设备环境& ctx, FILE* f) {
	C_从文件填充纹理节点* node = new C_从文件填充纹理节点(ctx);
	return node;
}

void		f_node_保存从文件填充纹理节点(C_节点基类* n, FILE* f) {
	C_从文件填充纹理节点* node = dynamic_cast<C_从文件填充纹理节点*>(n);
}





C_2D纹理采样节点::C_2D纹理采样节点(S_设备环境& ctx) : C_节点基类(DEF_2D纹理采样节点, E_节点类型::e_节点Type_纹理) {
	f_setWName(u"纹理2D采样");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建纹理插座_I(u"纹理", ctx);
	DEF_创建Vec2插座_I(u"纹理坐标", nullptr);

	DEF_创建Vec4插座_O(u"颜色", ctx);


	(DEF_Vec2插座数据(f_get输入插座(2), 0)) = { 0,0 };


	m_投影方式 = f_alloc_EnumProp(nullptr, { {u"平面", u"平面"}, {u"方体", u"立体线框"}, {u"球体", u"球体"}, {u"圆柱", u"圆柱"} }, u"序列偏移");
	m_投影方式.m_私有 = true;
	f_prop_enum(m_投影方式) = 0;

	m_采样方式 = f_alloc_EnumProp(nullptr, {
		{u"平滑", u""},
		{u"直接", u""},
		//{L"瓦片", ""},
		}, u"序列偏移");
	m_采样方式.m_私有 = true;


	f_构建代码_构建GPU插座变量(*f_get输入插座(2));
}

C_2D纹理采样节点::~C_2D纹理采样节点() {
	
	f_prop_Release(m_投影方式);
	f_prop_Release(m_采样方式);
	//f_prop_Release(m_瓦片数量);

	f_构建代码_释放GPU插座变量(*f_get输入插座(2));
}

bool C_2D纹理采样节点::f_update() {

	return false;
}

std::string C_2D纹理采样节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	std::string name = f_getName();

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);

	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);


	auto rt = f_getThis节点树();
	switch (rt->m_树类型) {
		case E_节点树类型::e_type_着色节点树: {
			socket2->f_upGPU块(0);
			switch (f_prop_enum(m_采样方式)) {
				case 0: {
					m_Code += "vec4 " + name + " = texture(Ts[nonuniformEXT(uint(" + socket1->f_getCode(0) + "))], " + socket2->f_getCode(0) + "); \n";
					break;
				}
				case 1: {
					m_Code += "vec4 " + name + " = texelFetch(Ts[nonuniformEXT(uint(" + socket1->f_getCode(0) + "))], " + socket2->f_getCode(0) + "); \n";
					break;
				}
				//case 2: {
				//	std::string 瓦片坐标 = DEF_S(mod)"(" + socket2->f_getCode(0) + ", " + f_代码构建_属性变量(m_瓦片数量, rt) + ");\n";
				//	m_Code += "vec4 " + name + " = texture(Ts[nonuniformEXT(uint(" + socket1->f_getCode(0) + "))]," + socket2->f_getCode(0) + "); \n";
				//	break;
				//}
			}
			break;
		}
		case E_节点树类型::e_type_材质节点树: {
		

			break;
		}
		default:
			break;
	}

	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_2D纹理采样节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_投影方式, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_2D纹理采样节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_投影方式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建纹理采样节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_2D纹理采样节点(ctx);
}

C_节点基类* f_node_加载纹理采样节点(S_设备环境& ctx, FILE* f) {
	C_2D纹理采样节点* node = new C_2D纹理采样节点(ctx);
	return node;
}

void f_node_保存纹理采样节点(C_节点基类* n, FILE* f) {
	C_2D纹理采样节点* node = dynamic_cast<C_2D纹理采样节点*>(n);
}





C_2D纹理数组采样节点::C_2D纹理数组采样节点(S_设备环境& ctx) : C_节点基类(DEF_2D纹理数组采样节点, E_节点类型::e_节点Type_纹理) {
	f_setWName(u"纹理数组2D采样");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建纹理插座_I(u"纹理", ctx);
	DEF_创建Vec3插座_I(u"纹理坐标", nullptr);

	DEF_创建Vec4插座_O(u"颜色", ctx);


	(DEF_Vec2插座数据(f_get输入插座(2), 0)) = { 0,0 };


	m_投影方式 = f_alloc_EnumProp(nullptr, { {u"平面", u"平面"}, {u"方体", u"立体线框"}, {u"球体", u"球体"}, {u"圆柱", u"圆柱"} }, u"序列偏移");
	m_投影方式.m_私有 = true;
	f_prop_enum(m_投影方式) = 0;

	m_采样方式 = f_alloc_EnumProp(nullptr, { 
		{u"平滑", u""}, 
		{u"直接", u""}, 
		}, u"序列偏移");
	m_采样方式.m_私有 = true;

}

C_2D纹理数组采样节点::~C_2D纹理数组采样节点() {
	f_prop_Release(m_投影方式);
}

bool C_2D纹理数组采样节点::f_update() {

	return false;
}

std::string C_2D纹理数组采样节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	std::string name = f_getName();

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);

	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);


	auto rt = f_getThis节点树();
	switch (rt->m_树类型) {
	case E_节点树类型::e_type_着色节点树: {
		switch (f_prop_enum(m_采样方式)) {
			case 0: {
				m_Code += "vec4 " + name + " = texture(Array2D_Ts[nonuniformEXT(uint(" + socket1->f_getCode(0) + "))]," + socket2->f_getCode(0) + "); \n";
				break;
			}
			case 1: {
				m_Code += "vec4 " + name + " = texelFetch(Array2D_Ts[nonuniformEXT(uint(" + socket1->f_getCode(0) + "))], ivec3(" + socket2->f_getCode(0) + "), 0); \n";
				break;
			}
		}
		
		break;
	}
	case E_节点树类型::e_type_材质节点树: {


		break;
	}
	default:
		break;
	}

	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code = m_Code;
		return "";
	}
	return m_Code;
}

void C_2D纹理数组采样节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_投影方式, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_采样方式, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_2D纹理数组采样节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_投影方式, 块);
	f_prop_Save(m_采样方式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建2D纹理数组采样节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_2D纹理数组采样节点(ctx);
}

C_节点基类* f_node_加载2D纹理数组采样节点(S_设备环境& ctx, FILE* f) {
	C_2D纹理数组采样节点* node = new C_2D纹理数组采样节点(ctx);
	return node;
}

void f_node_保存2D纹理数组采样节点(C_节点基类* n, FILE* f) {
	C_2D纹理数组采样节点* node = dynamic_cast<C_2D纹理数组采样节点*>(n);
}




void f_自动探测跟踪点(cv::Mat& 源图像, cv::Mat& 模板图像, std::vector<cv::Rect>& rect) {
	cv::Mat src;
	cv::Mat 目标图像;
	cv::matchTemplate(源图像, 模板图像, 目标图像, cv::TM_SQDIFF);
	cv::normalize(目标图像, 目标图像, 0, 255, cv::NORM_MINMAX);



	std::vector<float32> pro;  rect.clear();
	float64 mx = 0;  cv::Point loc, pre(-1, -1);


	uint32 num = 1;
	for (uint32 i = 0; i < num; ) {
		cv::minMaxLoc(目标图像, NULL, &mx, NULL, &loc);

		if (abs(loc.x - pre.x) > 10 && abs(loc.y - pre.y) > 10) {
			rect.push_back(cv::Rect(loc.x, loc.y, 模板图像.cols, 模板图像.rows));
			pre = loc;
			++i;
		}

		mx = 0;
		目标图像.at<float32>(loc.y, loc.x) = 0;
	}
	
}






/*static void f_Operator初始化跟踪点(S_结构对象指针 ops) {
	//C_节点面板* node = (C_节点面板*)ops;
	std::cout << "开始初始化跟踪点" << std::endl;
	C_流视频节点* 流视频节点 = ((C_流视频节点*)ops);

	if (流视频节点) {
		std::vector<S_Rect2Df> rects = 流视频节点->f_模板探测跟踪点({ 0, 10 }, { 0, 10 });

		if (rects.size()) {
			std::vector<S_RGBA8UI> color(rects.size(), { 50, 255, 50, 255 });
			f_ui_图像视口填充捕捉点(g当前视频视口->m_视频页面, rects, color);
		}
	}
}*/

cv::Ptr<cv::Tracker> f_create跟踪器类型(std::string type) {
	if (type == "CSRT") {
		return cv::TrackerCSRT::create();
		//m_跟踪器 = (S_结构对象指针)((cv::Tracker*)cv::TrackerCSRT::create());
	} else if (type == "KCF") {
		return cv::TrackerKCF::create();
	} else if (type == "MIL") {
		return cv::TrackerMIL::create();
	} else if (type == "MOSSE") {
		return cv::TrackerMOSSE::create();
	} else if (type == "GOTURN") {
		return cv::TrackerGOTURN::create();
	} else if (type == "TLD") {
		//m_跟踪器 = (S_结构对象指针)((cv::Tracker*)cv::TrackerTLD::create());
	} else if (type == "BOOSTING") {
		return cv::TrackerBoosting::create();
	} else if (type == "MEDIANFLOW") {
		return cv::TrackerMedianFlow::create();
	}

	return cv::TrackerTLD::create();
}











C_流视频节点::C_流视频节点(S_设备环境& ctx) : C_节点基类("流视频节点") {
	
	C_插座基类* socket;
	DEF_创建图像插座_I(u"像素");
	DEF_Rect32f_Array1D_插座创建_I(u"初始跟踪坐标")


	DEF_创建纹理插座_O(u"像素", ctx);
	DEF_Rect32f_Array1D_插座创建_O(u"跟踪坐标")


	g_多目标跟踪器[this] = cv::MultiTracker();
	f_set跟踪器类型("CSRT");

	m_帧 = (S_结构指针)new cv::Mat(512, 512, CV_8UC1);
	m_跟踪点数量 = 0;



	//m_Ops特效提取 = f_alloc_Ops(f_Operator初始化跟踪点, (S_结构对象指针)this);

	m_阈值步长 = 10;
	m_起始阈值 = 20;
	m_终止阈值 = 200;
	m_重复的最小次数 = 2;
	m_最小的斑点距离 = 10;

	m_斑点颜色限制 = true;
	m_斑点灰度 = 50;

	m_斑点面积限制 = true;
	m_斑点最小面积 = 25;
	m_斑点最大面积 = 5000;

	m_斑点面积限制 = true;
	m_斑点最小面积 = 4;
	m_斑点最大面积 = 1000;

	m_斑点圆度限制 = true;
	m_斑点最小圆度 = 0.8;
	m_斑点最大圆度 = 3.40282347e+38;

	m_斑点惯性率限制 = true;
	m_斑点最小惯性率 = 0.1;
	m_斑点最大惯性率 = 3.40282347e+38;

	m_斑点凸度限制 = true;
	m_斑点最小凸度 = 0.9;
	m_斑点最大凸度 = 3.40282347e+38;








	m_伽马 = 1.0;
	m_Prop伽马 = f_alloc_F32Prop(&m_伽马, u"伽马");
	
	m_亮度 = 0.0;
	m_Prop亮度 = f_alloc_F32Prop(&m_亮度, u"亮度");
	m_对比度 = 1.0;
	m_Prop对比度 = f_alloc_F32Prop(&m_对比度, u"对比度");

}

C_流视频节点::~C_流视频节点() {
	
}

bool C_流视频节点::f_update() {
	auto& inData = *DEF_图像插座Value(f_get输入插座(1));
	auto* outData = DEF_纹理插座数据(f_get输出插座(1), 0);

	auto* socketOut跟踪坐标 = f_get输出插座(2);
	auto& out跟踪坐标 = *DEF_Rect32f_Array1DValue(socketOut跟踪坐标, 0);

	


	if (inData.m_维度.x * inData.m_维度.y * inData.m_维度.z == 0) return false;
	

	/*auto* 初始跟踪坐标socket = f_get输入插座(2);
	if (初始跟踪坐标socket->f_isLink()) {
	}*/


	auto* p = inData.m_像素.data();


	//cv::VideoCapture capture;
	//cv::Mat img1(inData.m_维度.x, inData.m_维度.y, CV_8UC4);
	cv::Mat& frame = *((cv::Mat*)m_帧);
	//img1.create(inData.m_维度.x, inData.m_维度.y, CV_8UC4);
	frame.create(inData.m_维度.x, inData.m_维度.y, CV_8UC1);
	
	//cv::Mat img1(inData.m_维度.x, inData.m_维度.y, CV_8UC4);
	//Mat::isContinuous
	
	//cv::VideoWriter a;
	//capture>>img1;
	//img1.size[0] = inData.m_维度.x;
	//img1.size[1] = inData.m_维度.y;
	
	Concurrency::parallel_for<uint32>(0, inData.m_维度.y, [&](uint32 i){
		uint8* data = frame.ptr<uint8>(i);
		S_RGBA8UI* s = &(p[i * inData.m_维度.x]);

		for (uint32 j = 0; j < inData.m_维度.x; ++j) {
			//data[j] = cv::saturate_cast<uchar>(pow(s[j].r / 255.0, m_伽马) * 255.0);
			//saturate_cast <uchar>（pow（i / 255.0，gamma_） * 255.0）;
			/*s[j].r = cv::saturate_cast<uchar>(pow(s[j].r / 255.0, m_伽马) * 255.0);
			s[j].g = cv::saturate_cast<uchar>(pow(s[j].g / 255.0, m_伽马) * 255.0);
			s[j].b = cv::saturate_cast<uchar>(pow(s[j].b / 255.0, m_伽马) * 255.0);

			s[j].r = cv::saturate_cast<uchar>(s[j].r * m_对比度 + m_对比度);
			s[j].g = cv::saturate_cast<uchar>(s[j].g * m_对比度 + m_对比度);
			s[j].b = cv::saturate_cast<uchar>(s[j].b * m_对比度 + m_对比度);*/


			data[j] = s[j].r;
		}
	});


	f_ui_push纹理填充(outData, (uint8*)inData.m_像素.data(), inData.m_维度);






	cv::MultiTracker trackers;

	if (f_get输入插座(2)->m_有新数据) {
		

		std::vector<S_Rect2Df>& outCoord = *DEF_Rect32f_Array1DValue(f_get输入插座(2), 0);
		uint32 num = outCoord.size();

		//std::vector<cv::Rect> 初始跟踪区域;
		std::vector<cv::Rect2d> 初始跟踪区域(num);

		//static std::vector<cv::Ptr<cv::Tracker>> 跟踪算法;
		//跟踪算法.clear();
		g_目标跟踪器.resize(num);
		if (num) {
			m_跟踪点数量 = num;
			for (uint32 i = 0; i < num; ++i) {
			//for (auto& e : outCoord) {
				auto& e = outCoord[i];

				初始跟踪区域[i].x = e.offset.x;
				初始跟踪区域[i].y = e.offset.y;
				初始跟踪区域[i].width = e.extent.x;
				初始跟踪区域[i].height = e.extent.y;

				//跟踪算法.push_back(f_create跟踪器类型("CSRT"));

				g_目标跟踪器[i] = f_create跟踪器类型("CSRT");
				//g_目标跟踪器[i] = f_create跟踪器类型("MIL");
				if (i >= g_目标跟踪器.size()) {
					
					//g_目标跟踪器.push_back(f_create跟踪器类型("CSRT"));
					//g_目标跟踪器.push_back(f_create跟踪器类型("MOSSE"));
				}

				//m_跟踪器->init(frame, 初始跟踪区域[0]);
				g_目标跟踪器[i]->init(frame, 初始跟踪区域[i]);
			}

			
			//m_跟踪器->init(frame, 初始跟踪区域[0]);
			//cv::MultiTracker m;
			//m.add(f_create跟踪器类型("CSRT"), frame, cv::Rect2d());
			//g_多目标跟踪器[this].add(跟踪算法, frame, 初始跟踪区域);
		}
		//cv::selectROIs("rois", frame, 初始跟踪区域, false);
		return false;
	} else {
		
	}
	

	out跟踪坐标.resize(m_跟踪点数量);
	Concurrency::parallel_for<uint8>(0, m_跟踪点数量, [&](uint8 i){
		cv::Rect2d bbox;
		bool 追踪到 = g_目标跟踪器[i]->update(frame, bbox);
		if (追踪到) {
			out跟踪坐标[i].offset = { float32(bbox.x), float32(bbox.y) };
			out跟踪坐标[i].extent = { float32(bbox.width), float32(bbox.height) };

		} else {
			out跟踪坐标[i].offset = { 0, 0 };
			out跟踪坐标[i].extent = { 1, 1 };
		}
	});
	/*for (uint8 i = 0; i < m_跟踪点数量; ++i) {
		cv::Rect2d bbox;
		bool 追踪到 = g_目标跟踪器[i]->update(frame, bbox);
		if (追踪到) {
			out跟踪坐标[i].offset = { float32(bbox.x), float32(bbox.y) };
			out跟踪坐标[i].extent = { float32(bbox.width), float32(bbox.height) };

		} else {
			out跟踪坐标[i].offset = { 0, 0 };
			out跟踪坐标[i].extent = { 1, 1 };
		}
	}*/
	




	/*bool 跟踪到目标 = g_多目标跟踪器[this].update(frame);
	if (跟踪到目标) {
		for (auto j = 0; j < trackers.getObjects().size(); j++) {
			auto point = trackers.getObjects()[j];

			S_Rect2Df r;
			r.offset = {float32(point.x), float32(point.y)};
			r.extent = { float32(point.width), float32(point.height)};
			out跟踪坐标.push_back(r);
		}
	}*/


	return false;
	
}

void C_流视频节点::f_set跟踪器类型(std::string type) {
	if (type == "CSRT") {
		//m_跟踪器 = cv::TrackerCSRT::create();

		//m_跟踪器 = (S_结构对象指针)((cv::Tracker*)cv::TrackerCSRT::create());
	}else if (type == "KCF") {
		
	} else if (type == "MIL") {
		//m_跟踪器 = (S_结构对象指针)((cv::Tracker*)cv::TrackerTLD::create());
	} else if (type == "MOSSE") {
		
	} else if (type == "GOTURN") {

	} else if (type == "TLD") {
		//m_跟踪器 = (S_结构对象指针)((cv::Tracker*)cv::TrackerTLD::create());
	} else if (type == "BOOSTING") {
		//m_跟踪器 = (S_结构对象指针)((cv::Tracker*)cv::TrackerTLD::create());
	} else if (type == "MEDIANFLOW") {
		//m_跟踪器 = (S_结构对象指针)((cv::Tracker*)cv::TrackerTLD::create());
	}
	
}


void C_流视频节点::f_init跟踪器坐标(const vec2& coord, const vec2& size) {
	cv::Rect2d bbox;
	//cv::Tracker* tracker = (cv::Tracker*)m_跟踪器;

	bbox.x = coord.x;
	bbox.y = coord.y;

	bbox.width = size.x;
	bbox.height = size.y;

	cv::Mat img1(512, 512, CV_8UC4);
	//tracker->init(img1, bbox);
}

std::vector<S_Rect2Df> C_流视频节点::f_模板探测跟踪点(const vec2& cols, const vec2& rows) {
	//*((cv::Mat*)m_初始帧) = ((cv::Mat*)m_帧)->clone();
	cv::Mat& 源图像		= (*((cv::Mat*)m_帧));
	
	auto& 初始跟踪坐标 = *DEF_Rect32f_Array1DValue(f_get输入插座(2), 0);
	初始跟踪坐标.clear();

	if (rows.y - rows.x <= 0 || cols.y - cols.x <= 0) {
		std::cout << "模板尺寸不符合" << std::endl;
		return 初始跟踪坐标;
	}
	if (源图像.cols <= cols.x - cols.y || 源图像.rows <= rows.x - rows.y) {
		std::cout<<"模板尺寸不符合"<<std::endl;
		return 初始跟踪坐标;
	}
	
	//cv::Mat 副本 = 源图像.clone();
	//cv::Mat& 模板图像 = 源图像(cv::Range(cols.x, cols.y), cv::Range(rows.x, rows.y));


	cv::SimpleBlobDetector::Params params;

	params.thresholdStep = m_阈值步长;
	params.minThreshold = m_起始阈值;
	params.maxThreshold = m_终止阈值;
	params.minRepeatability = m_重复的最小次数;
	params.minDistBetweenBlobs = m_最小的斑点距离;
	//params.filterByCircularity = true;
	//params.minCircularity = 0.5;
	params.filterByColor = m_斑点颜色限制;
	params.blobColor = m_斑点灰度;

	params.filterByArea = m_斑点面积限制;
	params.minArea = m_斑点最小面积;
	params.maxArea = m_斑点最大面积;

	params.filterByCircularity = m_斑点圆度限制;
	params.minCircularity = m_斑点最小圆度;
	params.maxCircularity = m_斑点最大圆度;

	params.filterByInertia = m_斑点惯性率限制;
	params.minInertiaRatio = m_斑点最小惯性率;
	params.maxInertiaRatio = m_斑点最大惯性率;

	params.filterByConvexity = m_斑点凸度限制;
	params.minConvexity = m_斑点最小凸度;
	params.maxConvexity = m_斑点最大凸度;

	cv::Ptr<cv::SimpleBlobDetector> 斑点检测器 = cv::SimpleBlobDetector::create(params);
	
	//cv::SimpleBlobDetector 斑点检测器;
	static std::vector<cv::KeyPoint> KeyPoint;
	
	斑点检测器->detect(源图像, KeyPoint);
	//斑点检测器->compute(副本, KeyPoint, 模板图像);
	std::cout << KeyPoint.size() << std::endl;
	
	
	std::vector<S_Rect2Df> 返回数据;
	for (auto& e : KeyPoint) {
		S_Rect2Df r;

		r.offset.x = e.pt.x;
		r.offset.y = e.pt.y;

		r.extent.x = e.size;
		r.extent.y = e.size;

		初始跟踪坐标.push_back(r);
		返回数据.push_back(r);
	}

	f_标记输出插座新数据(2, true, E_插座方向::e_插座Type_输入);
	//auto& out跟踪坐标 = *DEF_Rect32f_Array1DValue(socketOut跟踪坐标, 0);
	return 返回数据;





	

	/*std::vector<cv::Rect> rect;
	f_自动探测跟踪点(源图像, 模板图像, rect);
	std::cout<< rect.size() << std::endl;

	std::vector<S_Rect2Df>& outCoord = *DEF_Rect32f_Array1DValue(f_get输出插座(2), 0);

	outCoord.resize(rect.size());
	uint32 i=0;
	for (auto& e : rect) {
		outCoord[i].offset = {float32(e.x), float32(e.y)};
		outCoord[i].extent = { float32(e.width), float32(e.height)};
		
	}
	
	f_标记输出插座新数据(2, true, E_插座输出方向::e_插座Type_输出);*/
	
}

void C_流视频节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			//下一次读取数据指针 = f_prop_Load(m_阈值步长, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);



	fread(&m_阈值步长, sizeof(int32), 1, f);
	fread(&m_起始阈值, sizeof(int32), 1, f);
	fread(&m_终止阈值, sizeof(int32), 1, f);
	fread(&m_重复的最小次数, sizeof(int32), 1, f);
	fread(&m_最小的斑点距离, sizeof(int32), 1, f);
	fread(&m_斑点颜色限制, sizeof(bool), 1, f);
	fread(&m_斑点灰度, sizeof(uint8), 1, f);
	fread(&m_斑点面积限制, sizeof(bool), 1, f);
	fread(&m_斑点最小面积, sizeof(int32), 1, f);
	fread(&m_斑点最大面积, sizeof(int32), 1, f);
	fread(&m_斑点圆度限制, sizeof(bool), 1, f);
	fread(&m_斑点最小圆度, sizeof(float32), 1, f);
	fread(&m_斑点最大圆度, sizeof(float32), 1, f);
	fread(&m_斑点惯性率限制, sizeof(bool), 1, f);
	fread(&m_斑点最小惯性率, sizeof(float32), 1, f);
	fread(&m_斑点最大惯性率, sizeof(float32), 1, f);
	fread(&m_斑点凸度限制, sizeof(bool), 1, f);
	fread(&m_斑点最小凸度, sizeof(float32), 1, f);
	fread(&m_斑点最大凸度, sizeof(float32), 1, f);

}

void C_流视频节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);



	fwrite(&m_阈值步长, sizeof(int32), 1, f);
	fwrite(&m_起始阈值, sizeof(int32), 1, f);
	fwrite(&m_终止阈值, sizeof(int32), 1, f);
	fwrite(&m_重复的最小次数, sizeof(int32), 1, f);
	fwrite(&m_最小的斑点距离, sizeof(int32), 1, f);
	fwrite(&m_斑点颜色限制, sizeof(bool), 1, f);
	fwrite(&m_斑点灰度, sizeof(uint8), 1, f);
	fwrite(&m_斑点面积限制, sizeof(bool), 1, f);
	fwrite(&m_斑点最小面积, sizeof(int32), 1, f);
	fwrite(&m_斑点最大面积, sizeof(int32), 1, f);
	fwrite(&m_斑点圆度限制, sizeof(bool), 1, f);
	fwrite(&m_斑点最小圆度, sizeof(float32), 1, f);
	fwrite(&m_斑点最大圆度, sizeof(float32), 1, f);
	fwrite(&m_斑点惯性率限制, sizeof(bool), 1, f);
	fwrite(&m_斑点最小惯性率, sizeof(float32), 1, f);
	fwrite(&m_斑点最大惯性率, sizeof(float32), 1, f);
	fwrite(&m_斑点凸度限制, sizeof(bool), 1, f);
	fwrite(&m_斑点最小凸度, sizeof(float32), 1, f);
	fwrite(&m_斑点最大凸度, sizeof(float32), 1, f);

}











C_节点基类* f_node_加载流视频节点(S_设备环境& ctx, FILE* f) {
	C_流视频节点* node = new C_流视频节点(ctx);

	return node;
}

C_噪波纹理节点::C_噪波纹理节点(S_设备环境& ctx) : C_节点基类(DEF_噪波纹理节点) {
	f_setWName(u"噪波");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建Vec3_1D插座_I(u"偏移", nullptr);
	DEF_创建Vec3_1D插座_I(u"缩放", nullptr);
	DEF_创建F32_1D插座_I(u"亮度", nullptr);
	DEF_创建UI32插座_I(u"模式");
	
	DEF_创建F32_1D插座_O(u"x");
	DEF_创建F32_1D插座_O(u"y");
	DEF_创建F32_1D插座_O(u"z");


	(DEF_UI32插座数据(f_get输入插座(4), 0)) = 0;

	m_过程纹理属性 = f_alloc_纹理属性(nullptr, u"纹理属性");
	m_过程纹理属性.m_私有 = true;

	m_通道数量 = f_alloc_EnumProp(nullptr, { {u"a", u""}, {u"xy", u""}, {u"rgb", u""} }, u"通道");
	m_通道数量.m_私有 = true;

	//m_偏移 = f_alloc_Vec2Prop(nullptr, L"偏移");
	//m_偏移.m_私有 = true;

	//m_缩放 = f_alloc_Vec2Prop(nullptr, L"缩放");
	//m_缩放.m_私有 = true;
	//m_强度 = f_alloc_F32Prop(nullptr, L"强度");
	//m_强度.m_私有 = true;

	//f_prop_Vec2(m_偏移) = {};
	//f_prop_Vec2(m_缩放) = {1,1};
	//f_prop_F32(m_强度) = 1;

	DEF_Vec3插座_1D数据(f_get输入插座(2))->ptr_userData[0] = { 1, 1, 1 };
	DEF_F32插座_1D数据(f_get输入插座(3))->ptr_userData[0] = 1;


	f_构建代码_分配渲染器GPU属性变量(m_过程纹理属性);

	f_构建代码_构建GPU插座变量(*f_get输入插座(1));
	f_构建代码_构建GPU插座变量(*f_get输入插座(2));
	f_构建代码_构建GPU插座变量(*f_get输入插座(3));
}

C_噪波纹理节点::~C_噪波纹理节点() {
	f_构建代码_释放GPU插座变量(*f_get输入插座(1));
	f_构建代码_释放GPU插座变量(*f_get输入插座(2));
	f_构建代码_释放GPU插座变量(*f_get输入插座(3));
}

bool C_噪波纹理节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	auto* socket3 = f_get输入插座(3);
	auto* socket4 = f_get输入插座(4);

	const auto& 偏移 = *DEF_Vec3插座_1D数据(f_get输入插座(1), 0);
	const auto& 缩放 = *DEF_Vec3插座_1D数据(f_get输入插座(2), 0);
	const auto& 亮度 = *DEF_F32插座_1D数据(f_get输入插座(3), 0);


	//vec2* 偏移_ptr = &f_prop_Vec2(m_偏移);
	//vec2* 缩放_ptr = &f_prop_Vec2(m_缩放);
	//float32* 亮度_ptr = &f_prop_F32(m_强度);

	vec3* 偏移_ptr;
	vec3* 缩放_ptr;
	float32* 亮度_ptr;

	bool 单例[3] = { true, true, true };
	uint32 num = 1;
	
	num = 偏移.count;
	偏移_ptr = 偏移.ptr_userData;
	单例[0] = false;
	
	缩放_ptr = 缩放.ptr_userData;
	if (缩放.count >= num) 单例[1] = false;

	亮度_ptr = 亮度.ptr_userData;
	if (亮度.count >= num) 单例[2] = false;


	
	uint32& 模式 = DEF_UI32插座数据(f_get输入插座(4), 0);
	S_F32Array* 噪波x = DEF_F32插座_1D数据(f_get输出插座(1), 0);
	S_F32Array* 噪波y = DEF_F32插座_1D数据(f_get输出插座(2), 0);
	S_F32Array* 噪波z = DEF_F32插座_1D数据(f_get输出插座(3), 0);

	f_JIT_简单噪波生成(num, 偏移_ptr, 缩放_ptr, 亮度_ptr, 单例, 噪波x, 0);
	f_JIT_简单噪波生成(num, 偏移_ptr, 缩放_ptr, 亮度_ptr, 单例, 噪波y, 124.3);
	f_JIT_简单噪波生成(num, 偏移_ptr, 缩放_ptr, 亮度_ptr, 单例, 噪波z, 3578.137);
	


	f_prop_TexProp(m_过程纹理属性).m_TexCoordOffset = 偏移_ptr[0];
	f_prop_TexProp(m_过程纹理属性).m_TexCoordScale = 缩放_ptr[0];
	f_prop_TexProp(m_过程纹理属性).m_Intensity = 亮度_ptr[0];
	f_prop_TexProp(m_过程纹理属性).m_TexColorMode = 模式;
	
	return false;
}

std::string C_噪波纹理节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	auto* rt = f_getThis节点树();
	auto name = f_getName();

	

	std::string name_x = name + "_x";
	std::string name_y = name + "_y";
	std::string name_z = name + "_z";

	bool 创建数组 = false;
	switch (rt->m_树类型) {
		case E_节点树类型::e_type_几何着色节点树:
		case E_节点树类型::e_type_并行节点树:
		case E_节点树类型::e_type_着色节点树: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_Vec3);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_Vec3);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 3, E_值类型::e_Type_F32);

			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 2, E_值类型::e_Type_F32);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 3, E_值类型::e_Type_F32);

			auto* socket1 = f_get输入插座(1);
			auto* socket2 = f_get输入插座(2);
			auto* socket3 = f_get输入插座(3);
			auto* socket4 = f_get输入插座(4);

			m_Code += "float " + name_x + ";\n";
			m_Code += "float " + name_y + ";\n";
			m_Code += "float " + name_z + ";\n";

			m_Code += "{\n";
			m_Code += socket1->f_构建变量代码(0);
			m_Code += socket2->f_构建变量代码(0);
			m_Code += socket3->f_构建变量代码(0);
			m_Code += socket4->f_构建变量代码(0);

			m_Code += name_x + " = " + DEF_S(f_glsl_simplexNoise)"(" + socket1->f_getCode(0) + ");\n";
			m_Code += name_y + " = " + DEF_S(f_glsl_simplexNoise)"(" + socket1->f_getCode(0) + " + 10);\n";
			m_Code += name_z + " = " + DEF_S(f_glsl_simplexNoise)"(" + socket1->f_getCode(0) + " + 30);\n";

			m_Code += m_ReleaseCode;
			m_Code += "}\n";
			break;
		}
		
		default : {
			auto* socket1 = f_get输入插座(1);
			auto* socket2 = f_get输入插座(2);
			auto* socket3 = f_get输入插座(3);
			auto* socket4 = f_get输入插座(4);

			m_Code += "S_F32Array* " + name_x + ";\n";
			m_Code += "S_F32Array* " + name_y + ";\n";
			m_Code += "S_F32Array* " + name_z + ";\n";
			创建数组 = true;
			m_Code += "{\n";

			m_Code += socket1->f_构建变量代码(0);
			m_Code += socket2->f_构建变量代码(0);
			m_Code += socket3->f_构建变量代码(0);
			m_Code += socket4->f_构建变量代码(0);


			m_Code += "bool 单例[3] = { false, true, true };\n";

			m_Code += "uint32 num = " + f_代码构建_Array数组数量(socket1->f_getCode(0)) + ";\n";
			m_Code += DEF_S(vec3*)" 偏移_ptr = (" + socket1->f_getCode(0) + ")->ptr_userData;\n";
			m_Code += DEF_S(vec3*)" 缩放_ptr = (" + socket2->f_getCode(0) + ")->ptr_userData;\n";
			m_Code += "float32* 亮度_ptr = (" + socket3->f_getCode(0) + ")->ptr_userData;\n";
			//if (socket3->f_isLink() == false) {
			//	m_Code += "亮度_ptr = &(" + f_代码构建_属性变量(m_强度, rt) + ");\n";
			//}
			m_Code += "if(num > 0){\n";

				m_Code += "if(num <=" + f_代码构建_Array数组数量(socket2->f_getCode(0)) + "){\n";
				m_Code += "	单例[1] = false;\n";
				m_Code += "}\n";

				m_Code += "if(num <=" + f_代码构建_Array数组数量(socket3->f_getCode(0)) + "){\n";
				m_Code += "	单例[2] = false;\n";
				m_Code += "}\n";

			m_Code += "}\n";
			m_Code += "else {\n";

			m_Code += "单例[0] = true;\n";
			m_Code += "num = 1;\n";

			m_Code += "}\n";


			m_Code += name_x + " = " + f_代码构建_创建Array(E_值类型::e_Type_F32_1D, "num") + ";\n";
			m_Code += DEF_S(f_JIT_简单噪波生成);
			m_Code += "(num, 偏移_ptr, 缩放_ptr, 亮度_ptr, 单例, " + name_x + ", 0);\n";

			m_Code += name_y + " = " + f_代码构建_创建Array(E_值类型::e_Type_F32_1D, "num") + ";\n";
			m_Code += DEF_S(f_JIT_简单噪波生成);
			m_Code += "(num, 偏移_ptr, 缩放_ptr, 亮度_ptr, 单例, " + name_y + ", 124.3);\n";

			m_Code += name_z + " = " + f_代码构建_创建Array(E_值类型::e_Type_F32_1D, "num") + ";\n";
			m_Code += DEF_S(f_JIT_简单噪波生成);
			m_Code += "(num, 偏移_ptr, 缩放_ptr, 亮度_ptr, 单例, " + name_z + ", 3578.137);\n";

			m_Code += m_ReleaseCode;
			m_Code += "}\n";
			break;
		}
	}
	

	f_get输出插座(1)->f_setCode(name_x);
	f_get输出插座(2)->f_setCode(name_y);
	f_get输出插座(3)->f_setCode(name_z);

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;

		if (创建数组) {
			m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name_x));
			m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name_y));
			m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name_z));
		}
		return "";
	}
	else {
		if (创建数组) {
			释放 += f_代码构建_销毁数组(name_x);
			释放 += f_代码构建_销毁数组(name_y);
			释放 += f_代码构建_销毁数组(name_z);
		}
	}
	return m_Code;
}

void C_噪波纹理节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_过程纹理属性, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_通道数量, 下一次读取数据指针);
			//下一次读取数据指针 = f_prop_Load(m_偏移, 下一次读取数据指针);
			//下一次读取数据指针 = f_prop_Load(m_缩放, 下一次读取数据指针);
			//下一次读取数据指针 = f_prop_Load(m_强度, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_噪波纹理节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_过程纹理属性, 块);
	f_prop_Save(m_通道数量, 块);
	//f_prop_Save(m_偏移, 块);
	//f_prop_Save(m_缩放, 块);
	//f_prop_Save(m_强度, 块);

	f_file_保存文件块(f, 文件块, 块);
}

void C_噪波纹理节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);

	//const C_噪波纹理节点* scr = dynamic_cast<const C_噪波纹理节点*>(node);
	//f_prop_Vec2(m_偏移) = f_prop_Vec2(scr->m_偏移);
	//f_prop_Vec2(m_缩放) = f_prop_Vec2(scr->m_缩放);
	//f_prop_F32(m_强度) = f_prop_F32(scr->m_强度);
}

C_节点基类* f_node_创建噪波纹理节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_噪波纹理节点(ctx);
}

C_节点基类* f_node_加载噪波纹理节点(S_设备环境& ctx, FILE* f) {
	C_噪波纹理节点* node = new C_噪波纹理节点(ctx);
	return node;
}

void f_node_保存噪波纹理节点(C_节点基类* n, FILE* f) {
	C_噪波纹理节点* node = dynamic_cast<C_噪波纹理节点*>(n);
}






C_渐变纹理节点::C_渐变纹理节点(S_设备环境& ctx) : C_节点基类(DEF_渐变纹理节点) {
	f_setWName(u"渐变");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建Vec3插座_I(u"采样坐标", nullptr);
	DEF_创建F32插座_O(u"亮度", nullptr);

	m_类型 = f_alloc_EnumProp(nullptr, { {u"线性", u""}, {u"球", u""}, {u"径向", u""} }, u"通道");
	m_类型.m_私有 = true;


	f_构建代码_分配渲染器GPU属性变量(m_类型);
	f_构建代码_构建GPU插座变量(*f_get输入插座(1));
}

C_渐变纹理节点::~C_渐变纹理节点() {
	f_prop_Release(m_类型);
}

bool C_渐变纹理节点::f_update() {

	return false;
}

std::string C_渐变纹理节点::DEF_节点编译函数{
	m_Code = "";
    m_ReleaseCode = "";

	auto* rt = f_getThis节点树();
	auto 类型 = f_代码构建_属性变量(m_类型, rt);
	auto name = f_getName();

	auto* socket1 = f_get输入插座(1);
	m_Code += socket1->f_构建变量代码(0);


	m_Code += "float " + name + " = f_texture_Gradient(" + socket1->f_getCode(0) + ", " + 类型 + ");\n";
	m_Code += m_ReleaseCode;

	f_get输出插座(1)->f_setCode(name);

	if (socket1->m_GPU缓存.m_Buf) {
		//((vec3*)socket1->m_GPU缓存->m_mappedPtr)[socket1->m_GPU内存偏移] = *DEF_Vec3插座数据(socket1, 0);
		f_buf_Vec3_at(socket1->m_GPU缓存) = DEF_Vec3插座数据(socket1);
	}
	f_buf_I32_at(m_类型.m_GPU缓存[0], 0) = f_prop_enum(m_类型);


	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;

		return "";
	}
	else {
		
	}
	return m_Code;
}

void C_渐变纹理节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_类型, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_渐变纹理节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_类型, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建渐变纹理节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_渐变纹理节点(ctx);
}

C_节点基类* f_node_加载渐变纹理节点(S_设备环境& ctx, FILE* f) {
	C_渐变纹理节点* node = new C_渐变纹理节点(ctx);
	return node;
}

void f_node_保存渐变纹理节点(C_节点基类* n, FILE* f) {
	C_渐变纹理节点* node = dynamic_cast<C_渐变纹理节点*>(n);
}






C_纹理UV坐标节点::C_纹理UV坐标节点(S_设备环境& ctx) : C_节点基类(DEF_噪波纹理节点) {
	f_setWName(u"UV");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建UI32插座_I(u"UV层", nullptr);

	DEF_创建Vec2插座_O(u"UV", nullptr);


	m_坐标类型 = f_alloc_EnumProp(nullptr, {
		{u"顶点", u""},
		{u"瓦片", u""},
	}, u"坐标类型");
	m_坐标类型.m_私有 = true;

}

C_纹理UV坐标节点::~C_纹理UV坐标节点() {
	f_prop_Release(m_坐标类型);
}

bool C_纹理UV坐标节点::f_update() {
	return false;
}

std::string C_纹理UV坐标节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	std::string name = f_getName();
	

	m_Code += "vec2 " + name + ";\n";

	auto* socket1 = f_get输入插座(1);
	m_Code += socket1->f_构建变量代码(0);

	std::string UV层 = socket1->f_getCode(0);
	m_Code += "if(" + UV层 + " < gGeom[callSceneData.InstanceIndex].uvLayerNum){\n";
	m_Code += "uvec3 uvIndex = uv_index.I[callSceneData.PrimitiveIndex + "+ UV层 + " * callSceneData.uvLayerOffset];\n";
	m_Code += "vec2 uv1 = uv_index.UV[uvIndex.x];\n";
	m_Code += "vec2 uv2 = uv_index.UV[uvIndex.y];\n";
	m_Code += "vec2 uv3 = uv_index.UV[uvIndex.z];\n";
	m_Code += name + " = uv1 * barycentrics.x + uv2.texCoord * barycentrics.y + uv3.texCoord * barycentrics.z;\n";
	m_Code += "} else {\n";
	m_Code += name + " = uv;\n";
	m_Code += "}\n";

	m_Code += m_ReleaseCode;



	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}
	else {
		//释放 += f_代码构建_销毁_Array(name);
	}
	return m_Code;
}

void C_纹理UV坐标节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_坐标类型, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_纹理UV坐标节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_坐标类型, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建纹理UV坐标节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_纹理UV坐标节点(ctx);
}

C_节点基类* f_node_加载纹理UV坐标节点(S_设备环境& ctx, FILE* f) {
	C_纹理UV坐标节点* node = new C_纹理UV坐标节点(ctx);
	return node;
}

void f_node_保存纹理UV坐标节点(C_节点基类* n, FILE* f) {
	C_纹理UV坐标节点* node = dynamic_cast<C_纹理UV坐标节点*>(n);
}



C_字符纹理节点::C_字符纹理节点(S_设备环境& ctx) : C_节点基类(DEF_字符纹理节点) {
	f_setWName(u"字符纹理");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建字符串插座_I(u"文本");
	DEF_创建I32插座_I(u"字体大小");
	DEF_创建字体插座_O(u"字体");

	DEF_I32插座数据(f_get输入插座(2)) = 20;

	m_字体文件 = f_alloc_PathProp(nullptr, u"字体文件");
	m_字体文件.m_私有 = true;

	m_字体.m_Tex = f_tex_创建图像纹理(ctx, { 16,16,1 }, E_纹理格式::e_tf_R8U_归一化, E_纹理维度类型::e_2D_Array);
	m_字体.m_Tex = f_scene_创建纹理(f_NodeCtx_get默认场景(), m_Ctx, u"文字默认空纹理", E_纹理分组类型::e_字符纹理, m_字体.m_Tex);

	//m_字符纹理表 = f_alloc_StrIndexProp(S_光追后端::G字符纹理, L"字符纹理");
	//m_字符纹理表.m_私有 = true;

	m_预设字符类型 = f_alloc_EnumProp(nullptr, {
		{u"自定义", u""},
		{u"数字",	u""},
		//{L"自定义", ""},
	}, u"预设字符类型");
	m_预设字符类型.m_私有 = true;

}

C_字符纹理节点::~C_字符纹理节点() {
	f_prop_Release(m_字体文件);
	//f_prop_Release(m_字符纹理表);

	f_scene_销毁纹理(f_NodeCtx_get默认场景(), m_字体.m_Tex, E_纹理分组类型::e_字符纹理);
}

bool C_字符纹理节点::f_update() {
	auto& path = f_prop_Path(m_字体文件);
	auto& 文本 = f_prop_LineStr(DEF_字符串插座数据(f_get输入插座(1)));

	//if (m_以加载文件记录 != path && 文本.size()) {
		m_以加载文件记录 = path.string();
		if (false == f_file_文件是否存在(m_以加载文件记录)) {
			m_以加载文件记录 = "";
			return false;
		}

		auto* socket1Out = f_get输出插座(1);
		
		auto& 大小 = DEF_I32插座数据(f_get输入插座(2));

		//auto& 字体 = DEF_字体插座数据(f_get输出插座(1));

		S_字体加载参数 字体加载参数;
		字体加载参数.m_名称 = f_getName();
		字体加载参数.m_字体文件路径 = f_prop_Path(m_字体文件).string();
		字体加载参数.m_字号 = 大小;
		
		m_字体.m_字号 = 大小;


		f_surface_加链字体纹理(m_Ctx, m_字体, 字体加载参数, 文本);
		f_scene_更新配置内部纹理(f_NodeCtx_get默认场景());
		//std::vector<uint8> 默认字符纹理填充(16 * 16, 255);
		//f_tex_填充纹理数据(m_字体.m_Tex, 默认字符纹理填充.data(), sizeof(uint8), { 16,16,1 });
		//f_scene_创建纹理()

		socket1Out->f_setData(&m_字体);
	//}

	switch (f_prop_enum(m_预设字符类型)) {
		case 0: {
			break;
		}
		case 1: {
			break;
		}
		default:
			break;
	}

	return false;
}

std::string C_字符纹理节点::DEF_节点编译函数 {
	m_Code = "";
	m_ReleaseCode = "";

	auto* rt = f_getThis节点树();
	auto name = f_getName();


	auto& path = f_prop_Path(m_字体文件);
	if (m_以加载文件记录 != path) {
		m_以加载文件记录 = path.string();

		auto& 文本 = DEF_Str插座Value(f_get输入插座(1), 0);

		//f_scene_创建纹理()
	}



	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}
	return m_Code;
}

void C_字符纹理节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			//下一次读取数据指针 = f_prop_Load(m_字符纹理表, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_字体文件, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_字符纹理节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	//f_prop_Save(m_字符纹理表, 块);
	f_prop_Save(m_字体文件, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建字符纹理节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_字符纹理节点(ctx);
}

C_节点基类* f_node_加载字符纹理节点(S_设备环境& ctx, FILE* f) {
	C_字符纹理节点* node = new C_字符纹理节点(ctx);
	return node;
}

void f_node_保存字符纹理节点(C_节点基类* n, FILE* f) {
	C_字符纹理节点* node = dynamic_cast<C_字符纹理节点*>(n);
}




C_棋盘格纹理节点::C_棋盘格纹理节点(S_设备环境& ctx) : C_节点基类(DEF_棋盘格纹理节点) {
	f_setWName(u"棋盘格纹理");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建Vec3插座_I(u"采样坐标", nullptr);
	DEF_创建Vec3插座_I(u"大小", nullptr);

	DEF_创建F32插座_O(u"值", nullptr);

	f_构建代码_构建GPU插座变量(*f_get输入插座(1));
	f_构建代码_构建GPU插座变量(*f_get输入插座(2));

}

C_棋盘格纹理节点::~C_棋盘格纹理节点() {

}

bool C_棋盘格纹理节点::f_update() {
	return false;
}

std::string C_棋盘格纹理节点::DEF_节点编译函数{
	m_Code = "";
    m_ReleaseCode = "";

	auto* rt = f_getThis节点树();
	auto name = f_getName();

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);

	switch (rt->m_树类型)
	{
	case E_节点树类型::e_type_着色节点树: {
		m_Code += "float " + name + " = f_texture_Checker(" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ");\n";

		if (socket1->f_isLink() == false && socket1->m_GPU缓存.m_Buf) {
			f_buf_Vec3_at(socket1->m_GPU缓存) = DEF_Vec3插座数据(socket1);
		}
		if (socket2->f_isLink() == false && socket2->m_GPU缓存.m_Buf) {
			f_buf_Vec3_at(socket2->m_GPU缓存) = DEF_Vec3插座数据(socket2);
		}

		break;
	}
	default:
		break;
	}
	
	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}
	return m_Code;
}

void C_棋盘格纹理节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			//下一次读取数据指针 = f_prop_Load(m_外部加载, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_棋盘格纹理节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	//f_prop_Save(m_外部加载, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建棋盘格纹理节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_棋盘格纹理节点(ctx);
}

C_节点基类* f_node_加载棋盘格纹理节点(S_设备环境& ctx, FILE* f) {
	C_棋盘格纹理节点* node = new C_棋盘格纹理节点(ctx);
	return node;
}

void f_node_保存棋盘格纹理节点(C_节点基类* n, FILE* f) {
	C_棋盘格纹理节点* node = dynamic_cast<C_棋盘格纹理节点*>(n);
}




C_字符纹理坐标节点::C_字符纹理坐标节点(S_设备环境& ctx) : C_节点基类(DEF_字符纹理坐标节点) {
	f_setWName(u"字符纹理坐标");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建字体插座_I(u"字体");
	DEF_创建字符串插座_I(u"文本");

	DEF_创建Vec3_1D插座_O(u"字符纹理坐标");
	DEF_创建Vec2_1D插座_O(u"字符宽度");


	m_坐标类型 = f_alloc_EnumProp(nullptr, { 
		{u"线性", u""}, 
		{u"直接", u""}, 
	}, u"通道");
	m_坐标类型.m_私有 = true;
}

C_字符纹理坐标节点::~C_字符纹理坐标节点() {
	f_prop_Release(m_坐标类型);
}

bool C_字符纹理坐标节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);


	auto& 字体 = DEF_字体插座数据(socket1);
	auto& 字符串 = DEF_字符串插座数据(socket2);

	return false;
}

std::string C_字符纹理坐标节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	auto* rt = f_getThis节点树();
	auto name1 = f_getName() + "_纹理坐标";
	auto name2 = f_getName() + "_字符宽度";

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);

	m_Code += DEF_S(S_Vec3Array*)" " + name1 + " = " + f_代码构建_创建数组(E_值类型::e_Type_Vec3_1D, 1);
	m_Code += DEF_S(S_Vec2Array*)" " + name2 + " = " + f_代码构建_创建数组(E_值类型::e_Type_Vec2_1D, 1);
	m_Code += "{\n";
	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);

	m_Code += DEF_S(f_JIT_get字符纹理坐标)"(" + socket1->f_getCode(0) 
											+ ", " + socket2->f_getCode(0) 
											+ ", " + name1 
											+ ", " + name2 
											+ ", (int32*)" + DEF_指针转字符串(&f_prop_enum(m_坐标类型)) + ");\n";

	m_Code += m_ReleaseCode;
	m_Code += "}\n";
	


	f_get输出插座(1)->f_setCode(name1);
	f_get输出插座(2)->f_setCode(name2);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		m_区域父节点->m_ReleaseCode += f_代码构建_销毁数组(name1);
		m_区域父节点->m_ReleaseCode += f_代码构建_销毁数组(name2);
		return "";
	}
	释放 += f_代码构建_销毁数组(name1);
	释放 += f_代码构建_销毁数组(name2);
	return m_Code;
}

void C_字符纹理坐标节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_坐标类型, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_字符纹理坐标节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_坐标类型, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建字符纹理坐标节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_字符纹理坐标节点(ctx);
}

C_节点基类* f_node_加载字符纹理坐标节点(S_设备环境& ctx, FILE* f) {
	C_字符纹理坐标节点* node = new C_字符纹理坐标节点(ctx);
	return node;
}

void f_node_保存字符纹理坐标节点(C_节点基类* n, FILE* f) {
	C_字符纹理坐标节点* node = dynamic_cast<C_字符纹理坐标节点*>(n);
}




C_字符纹理排列节点::C_字符纹理排列节点(S_设备环境& ctx) : C_节点基类(DEF_字符纹理排列节点) {
	f_setWName(u"字符纹理坐标");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建字体插座_I(u"字体");
	DEF_创建字符串插座_I(u"文本");

	DEF_创建Vec2_1D插座_O(u"偏移坐标");
	DEF_创建Vec2_1D插座_O(u"字符大小");

	m_排列方向 = f_alloc_EnumProp(nullptr, {
		{u"横向", u""},
		{u"纵向", u""},
							  }, u"通道");
	m_排列方向.m_私有 = true;

	m_上下偏移 = f_alloc_F32Prop(nullptr, u"上下偏移");
	m_上下偏移.m_私有 = true;

	m_间隔 = f_alloc_F32Prop(nullptr, u"间隔");
	m_间隔.m_私有 = true;

	m_行距 = f_alloc_F32Prop(nullptr, u"行距");
	m_行距.m_私有 = true;

	m_缩放 = f_alloc_F32Prop(nullptr, u"缩放");
	m_缩放.m_私有 = true;

	f_prop_F32(m_上下偏移) = 0;
	f_prop_F32(m_间隔) = 0;
	f_prop_F32(m_行距) = 0;
	f_prop_F32(m_缩放) = 1;
}

C_字符纹理排列节点::~C_字符纹理排列节点() {
	f_prop_Release(m_排列方向);
	f_prop_Release(m_上下偏移);
	f_prop_Release(m_间隔);
	f_prop_Release(m_行距);
	f_prop_Release(m_缩放);
}

bool C_字符纹理排列节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);


	auto& 字体 = DEF_字体插座数据(socket1);
	auto& 字符串 = DEF_字符串插座数据(socket2);

	return false;
}

std::string C_字符纹理排列节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	auto* rt = f_getThis节点树();
	//auto name = f_getName();
	auto name1 = f_getName() + "_纹理坐标";
	auto name2 = f_getName() + "_字符宽度";

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);

	m_Code += DEF_S(S_Vec2Array*)" " + name1 + " = " + f_代码构建_创建数组(E_值类型::e_Type_Vec2_1D, 1);
	m_Code += DEF_S(S_Vec2Array*)" " + name2 + " = " + f_代码构建_创建数组(E_值类型::e_Type_Vec2_1D, 1);
	//m_Code += DEF_S(S_F32Array*)" " + name + " = " + f_代码构建_创建数组(E_值类型::e_Type_Vec2_1D, 1);
	m_Code += "{\n";
	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);

	m_Code += DEF_S(f_JIT_get字符纹理排列)"(" + socket1->f_getCode(0)
		+ ", " + socket2->f_getCode(0)
		+ ", " + name1
		+ ", " + name2
		+ ", (int32*)" + DEF_指针转字符串(&f_prop_enum(m_排列方向))
		+ ", " + f_代码构建_属性变量(m_缩放, rt)
		+ ", " + f_代码构建_属性变量(m_间隔, rt)
		+ ", " + f_代码构建_属性变量(m_上下偏移, rt) + ");\n";

	m_Code += m_ReleaseCode;
	m_Code += "}\n";


	f_get输出插座(1)->f_setCode(name1);
	f_get输出插座(2)->f_setCode(name2);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name1));
		m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name2));
		return "";
	}
	释放 += f_代码构建_销毁数组(name1);
	释放 += f_代码构建_销毁数组(name2);
	return m_Code;
}

void C_字符纹理排列节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_排列方向, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_上下偏移, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_间隔, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_行距, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_缩放, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_字符纹理排列节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_排列方向, 块);
	f_prop_Save(m_上下偏移, 块);
	f_prop_Save(m_间隔, 块);
	f_prop_Save(m_行距, 块);
	f_prop_Save(m_缩放, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建字符纹理排列节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_字符纹理排列节点(ctx);
}

C_节点基类* f_node_加载字符纹理排列节点(S_设备环境& ctx, FILE* f) {
	C_字符纹理排列节点* node = new C_字符纹理排列节点(ctx);
	return node;
}

void f_node_保存字符纹理排列节点(C_节点基类* n, FILE* f) {
	C_字符纹理排列节点* node = dynamic_cast<C_字符纹理排列节点*>(n);
}




C_重置纹理大小节点::C_重置纹理大小节点(S_设备环境& ctx) : C_节点基类(DEF_重置纹理大小节点) {
	f_setWName(u"重置图像大小");
	m_Ctx = ctx;

	DEF_创建纹理插座_I(u"图像", m_Ctx);
	DEF_创建uVec2插座_I(u"分辨率");
	DEF_创建纹理插座_O(u"目标图像", m_Ctx);
	
	DEF_uVec2插座数据(f_get输入插座(2)) = {8,8};


	m_复制 = f_alloc_BoolProp(nullptr, u"复制");
	m_复制.m_私有 = true;
	f_prop_Bool(m_复制) = true;


	m_新建纹理 = nullptr;
	m_自定义更新方式 = true;
}

C_重置纹理大小节点::~C_重置纹理大小节点() {
	f_prop_Release(m_复制);
	if (m_新建纹理) {
		f_tex_销毁纹理(m_新建纹理);
	}
}

bool C_重置纹理大小节点::f_update() {
	auto* 源图像 = DEF_纹理插座数据(f_get输入插座(1));
	auto& 分辨率 = DEF_uVec2插座数据(f_get输入插座(2));


	auto* outSocket1 = f_get输出插座(1);
	
	S_纹理* 目标图像;
	if (f_prop_Bool(m_复制)) {
		if (!m_新建纹理) {
			//m_新建纹理 = f_tex_创建图像纹理(m_Ctx, { 分辨率.x, 分辨率.y, 1 }, E_纹理格式::e_tf_RGBA8U_U, E_纹理维度类型::e_2D);
			m_新建纹理 = f_tex_创建图像(m_Ctx, { 分辨率.x, 分辨率.y, 1 }, E_纹理格式::e_tf_RGBA8U_归一化, E_纹理维度类型::e_2D);
		}
		outSocket1->f_setData(m_新建纹理);
		目标图像 = m_新建纹理;
	}
	else {
		f_get输出插座(1)->f_setData(源图像);
		目标图像 = 源图像;
	}

	if (f_prop_Bool(m_更新方式属性)) {
		if (S_节点数据::g_开启节点帧更新) {
			f_tex_重置2D纹理大小(源图像, 目标图像, 分辨率);
		}
	}
	else {
		f_tex_重置2D纹理大小(源图像, 目标图像, 分辨率);
	}
	
	return false;
}

std::string C_重置纹理大小节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	std::string name = f_getName();

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	

	m_Code += DEF_S(S_纹理*)" " + name + ";\n";
	

	m_Code += "{\n";
	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);

	if (f_prop_Bool(m_复制)) {
		//m_Code += name + " = " + DEF_S(f_tex_创建图像纹理)"(*(S_设备环境*)" + DEF_指针转字符串(&m_Ctx) + ", {2,2,1}" + ", E_纹理格式::e_tf_RGBA8U_U, E_纹理维度类型::e_2D, E_MS次数::e_MS_1, E_纹理排列::e_瓦片);\n";
		m_Code += name + " = " + DEF_S(f_tex_创建图像)"(*(S_设备环境*)" + DEF_指针转字符串(&m_Ctx) + ", {2,2,1}" + ", E_纹理格式::e_tf_RGBA8U_归一化, E_纹理维度类型::e_2D);\n";
	}
	else {
		name = socket1->f_getCode(0);
	}

	//if (f_prop_Bool(m_更新方式属性)) {
	//	m_Code += "if(";
	//	m_Code += DEF_S(*DEF_全局变量_g_执行状态离线_)"){\n";
	//
	//	m_Code += DEF_S(f_tex_重置2D纹理大小)"(" + socket1->f_getCode(0) + ", " + name + ", " + socket2->f_getCode(0) + ");\n";
	//
	//	m_Code += "}\n";
	//}
	//else {
	//	m_Code += DEF_S(f_tex_重置2D纹理大小)"(" + socket1->f_getCode(0) + "," + name + "," + socket2->f_getCode(0) + ");\n";
	//}
	m_Code += DEF_S(f_tex_重置2D纹理大小)"(" + socket1->f_getCode(0) + "," + name + "," + socket2->f_getCode(0) + ");\n";

	m_Code += m_ReleaseCode;
	m_Code += "}\n";

	

	f_get输出插座(2)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		if (f_prop_Bool(m_复制)) {
			m_区域父节点->m_ReleaseCode.insert(0, DEF_S(f_tex_销毁纹理)"(" + name + ");\n");
		}
		return "";
	}
	if (f_prop_Bool(m_复制)) {
		释放 += DEF_S(f_tex_销毁纹理)"(" + name + ");\n";
	}
	return m_Code;
}

void C_重置纹理大小节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_复制, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_重置纹理大小节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_复制, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建重置纹理大小节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_重置纹理大小节点(ctx);
}

C_节点基类* f_node_加载重置纹理大小节点(S_设备环境& ctx, FILE* f) {
	C_重置纹理大小节点* node = new C_重置纹理大小节点(ctx);
	return node;
}

void f_node_保存重置纹理大小节点(C_节点基类* n, FILE* f) {
	C_重置纹理大小节点* node = dynamic_cast<C_重置纹理大小节点*>(n);
}




C_纹理写入文件节点::C_纹理写入文件节点(S_设备环境& ctx) : C_节点基类(DEF_纹理写入文件节点) {
	f_setWName(u"图像写入文件");
	m_Ctx = ctx;

	DEF_创建纹理插座_I(u"图像", m_Ctx);
	DEF_创建字符串插座_I(u"路径");


	m_保存格式 = f_prop_创建图像格式类型属性数据();
	m_保存格式.m_私有 = true;

	m_像素位宽 = f_prop_创建图像位宽类型属性数据();
	m_像素位宽.m_私有 = true;

	m_保存方式 = f_prop_创建写入方式属性数据();
	m_保存方式.m_私有 = true;
	f_prop_enum(m_保存方式) = 0;

	//m_自定义更新方式 = true;
}

C_纹理写入文件节点::~C_纹理写入文件节点() {
	f_prop_Release(m_保存格式);
	f_prop_Release(m_像素位宽);
	f_prop_Release(m_保存方式);
}

bool C_纹理写入文件节点::f_update() {
	
	S_Props 文件路径 = DEF_字符串插座数据(f_get输入插座(2));
	f_file_补充路径后缀(文件路径, m_保存格式);

	f_tex_纹理保存到文件(DEF_纹理插座数据(f_get输入插座(1)), 文件路径, m_保存格式, m_保存方式);
	return false;
}

std::string C_纹理写入文件节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);


	m_Code += "{\n";
	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);

	auto 格式 = "*(S_Props*)" + DEF_指针转字符串(&m_保存格式);
	auto 保存方式 = "*(S_Props*)" + DEF_指针转字符串(&m_保存方式);
	m_Code += DEF_S(f_file_补充路径后缀)"(" + socket2->f_getCode(0) + ", " + 格式 + ");\n";
	//if (f_prop_Bool(m_更新方式属性)) {
	//	m_Code += "if(";
	//	m_Code += DEF_S(*DEF_全局变量_g_执行状态离线_)"){\n";
	//
	//	m_Code += DEF_S(f_tex_纹理保存到文件)"(" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + 格式 + ", " + 保存方式 + ");\n";
	//
	//	m_Code += "}\n";
	//}
	//else {
	//	m_Code += DEF_S(f_tex_纹理保存到文件)"(" + socket1->f_getCode(0) + "," + socket2->f_getCode(0) + ", " + 格式 + ", " + 保存方式 + ");\n";
	//}
	m_Code += DEF_S(f_tex_纹理保存到文件)"(" + socket1->f_getCode(0) + "," + socket2->f_getCode(0) + ", " + 格式 + ", " + 保存方式 + ");\n";

	m_Code += m_ReleaseCode;
	m_Code += "}\n";


	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}
	return m_Code;
}

void C_纹理写入文件节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_保存格式, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_像素位宽, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_保存方式, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_纹理写入文件节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_保存格式, 块);
	f_prop_Save(m_像素位宽, 块);
	f_prop_Save(m_保存方式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建纹理写入文件节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_纹理写入文件节点(ctx);
}

C_节点基类* f_node_加载纹理写入文件节点(S_设备环境& ctx, FILE* f) {
	C_纹理写入文件节点* node = new C_纹理写入文件节点(ctx);
	return node;
}

void f_node_保存纹理写入文件节点(C_节点基类* n, FILE* f) {
	C_纹理写入文件节点* node = dynamic_cast<C_纹理写入文件节点*>(n);
}





C_取纹理属性节点::C_取纹理属性节点(S_设备环境& ctx) : C_节点基类(DEF_取纹理属性节点, E_节点类型::e_节点Type_纹理) {
	f_setWName(u"取纹理属性");
	m_Ctx = ctx;

	DEF_创建纹理插座_I(u"图像", m_Ctx);
	DEF_创建uVec2插座_O(u"分辨率");
	DEF_创建UI32插座_O(u"像素位宽");
	DEF_创建UI32插座_O(u"通道数量");
}

C_取纹理属性节点::~C_取纹理属性节点() {

}

bool C_取纹理属性节点::f_update() {
	S_纹理* 纹理 = DEF_纹理插座数据(f_get输入插座(1));

	uvec2 分辨率 = { 纹理->m_Size.x, 纹理->m_Size.y };
	uint32 位宽 = 8;
	uint32 通道 = 4;
	
	f_get输出插座(1)->f_setData(&分辨率);
	f_get输出插座(2)->f_setData(&位宽);
	f_get输出插座(3)->f_setData(&通道);

	return false;
}

std::string C_取纹理属性节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	auto name = f_getName();

	auto* socket1 = f_get输入插座(1);
	auto* outSocket1 = f_get输出插座(1);
	auto* outSocket2 = f_get输出插座(2);
	auto* outSocket3 = f_get输出插座(3);

	auto 分辨率 = name + "_分辨率";
	auto 位宽 = name + "_位宽";
	auto 通道 = name + "_通道";

	m_Code += DEF_S(uvec2)" " + 分辨率 + "{};\n";
	m_Code += DEF_S(uint32)" " + 位宽 + "{};\n";
	m_Code += DEF_S(uint32)" " + 通道 + "{};\n";
	m_Code += "{\n";
	m_Code += socket1->f_构建变量代码(0);

	m_Code += DEF_S(f_JIT_get纹理属性)"(" + socket1->f_getCode(0) + ", " + 分辨率 + ", " + 位宽 + ", " + 通道 + ");\n";

	m_Code += m_ReleaseCode;
	m_Code += "}\n";

	outSocket1->f_setCode(分辨率);
	outSocket2->f_setCode(位宽);
	outSocket3->f_setCode(通道);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}
	return m_Code;
}

void C_取纹理属性节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			//下一次读取数据指针 = f_prop_Load(m_保存格式, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_取纹理属性节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	//f_prop_Save(m_保存格式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建取纹理属性节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_取纹理属性节点(ctx);
}

C_节点基类* f_node_加载取纹理属性节点(S_设备环境& ctx, FILE* f) {
	C_取纹理属性节点* node = new C_取纹理属性节点(ctx);
	return node;
}

void f_node_保存取纹理属性节点(C_节点基类* n, FILE* f) {
	C_取纹理属性节点* node = dynamic_cast<C_取纹理属性节点*>(n);
}




C_瓦片纹理坐标节点::C_瓦片纹理坐标节点(S_设备环境& ctx) : C_节点基类(DEF_瓦片纹理坐标节点, E_节点类型::e_节点Type_计算) {
	f_setWName(u"瓦片坐标");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建Vec2插座_I(u"采样坐标");
	DEF_创建iVec2插座_I(u"瓦块ID");
	DEF_创建Vec2插座_O(u"纹理坐标");


	m_瓦片数量 = f_alloc_iVec2Prop(nullptr, u"瓦片数量", { 2,2 }, 1, 2048);
	m_瓦片数量.m_私有 = true;

	m_瓦片大小 = f_alloc_Vec2Prop(nullptr, u"瓦片大小", { 0.5f,0.5f }, 0, 65536);
	m_瓦片大小.m_私有 = true;

	m_坐标类型 = f_alloc_EnumProp(nullptr, {
		{u"缩放到区域"},
		{u"缩放到区域保持比例"},
		{u"使用切分的区域"},
	}, u"坐标类型", 0);
	m_坐标类型.m_私有 = true;

	//f_prop_iVec2(m_瓦片数量) = { 2,2 };
	//f_prop_Vec2(m_瓦片大小) = {0.5f,0.5f};
	//f_prop_enum(m_坐标类型) = 0;

	f_构建代码_分配渲染器GPU属性变量(m_瓦片数量);
	f_构建代码_分配渲染器GPU属性变量(m_瓦片大小);

	f_构建代码_构建GPU插座变量(*f_get输入插座(1));
	f_构建代码_构建GPU插座变量(*f_get输入插座(2));
}

C_瓦片纹理坐标节点::~C_瓦片纹理坐标节点() {
	f_构建代码_释放渲染器GPU属性变量(m_瓦片数量);
	f_构建代码_释放渲染器GPU属性变量(m_瓦片大小);

	f_构建代码_释放GPU插座变量(*f_get输入插座(1));
	f_构建代码_释放GPU插座变量(*f_get输入插座(2));

	f_prop_Release(m_瓦片数量);
	f_prop_Release(m_瓦片大小);
	f_prop_Release(m_坐标类型);
}

bool C_瓦片纹理坐标节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	//auto* socket3 = f_get输入插座(3);

	vec2 瓦片大小 = f_prop_Vec2(m_瓦片大小);
	vec2 coord{};
	switch (f_prop_enum(m_坐标类型)) {
		case 0:
			coord = f_TileTextureSamplCoord(DEF_Vec2插座数据(socket1), 瓦片大小, DEF_iVec2插座数据(socket2));
			break;
		case 1:
			coord = f_TileTextureSamplkeepCoord(DEF_Vec2插座数据(socket1), 瓦片大小, DEF_iVec2插座数据(socket2));
			break;
		case 2:
			coord = f_TileTextureSamplLocCoord(DEF_Vec2插座数据(socket1), 瓦片大小, DEF_iVec2插座数据(socket2));
			break;
	}
	
	f_get输出插座(1)->f_setData(&coord);
	return false;
}

std::string C_瓦片纹理坐标节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	auto name = f_getName();

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	//auto* socket3 = f_get输入插座(3);

	auto* outSocket1 = f_get输出插座(1);

	auto rt = f_getThis节点树();

	m_Code += DEF_S(vec2)" " + name + ";\n";
	m_Code += "{\n";
	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);

	switch (rt->m_树类型) {
		case E_节点树类型::e_type_着色节点树: {
			m_Code += name + " = ";
			auto 瓦片大小 = f_代码构建_属性变量(m_瓦片大小, rt);

			switch (f_prop_enum(m_坐标类型)) {
				case 0:
					m_Code += DEF_S(f_TileTextureSamplCoord)"(" + socket1->f_getCode(0) + ", " + 瓦片大小 + ", " + socket2->f_getCode(0) + ");\n";
					break;
				case 1:
					m_Code += DEF_S(f_TileTextureSamplkeepCoord)"(" + socket1->f_getCode(0) + ", " + 瓦片大小 + ", " + socket2->f_getCode(0) + ");\n";
					break;
				case 2:
					m_Code += DEF_S(f_TileTextureSamplLocCoord)"(" + socket1->f_getCode(0) + ", " + 瓦片大小 + ", " + socket2->f_getCode(0) + ");\n";
					break;
			}
			
			f_代码构建_属性变量传至GPU(m_瓦片大小);

			socket1->f_getGPU块(0, true);
			socket2->f_getGPU块(0, true);
			break;
		}
		default: {
			
			m_Code += socket1->f_构建变量代码(0);
			//m_Code += DEF_S(f_JIT_get纹理属性)"(" + socket1->f_getCode(0) + ", " + 分辨率 + ", " + 位宽 + ", " + 通道 + ");\n";

			break;
		}
	}
	m_Code += m_ReleaseCode;
	m_Code += "}\n";

	//m_Code += DEF_S(vec2)" " + 采样坐标 + "{};\n";
	//m_Code += DEF_S(uint32)" " + 位宽 + "{};\n";
	//m_Code += DEF_S(uint32)" " + 通道 + "{};\n";
	

	outSocket1->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}
	return m_Code;
}

void C_瓦片纹理坐标节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_瓦片数量, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_瓦片大小, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_坐标类型, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_瓦片纹理坐标节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_瓦片数量, 块);
	f_prop_Save(m_瓦片大小, 块);
	f_prop_Save(m_坐标类型, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建瓦片纹理坐标节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_瓦片纹理坐标节点(ctx);
}

C_节点基类* f_node_加载瓦片纹理坐标节点(S_设备环境& ctx, FILE* f) {
	C_瓦片纹理坐标节点* node = new C_瓦片纹理坐标节点(ctx);
	return node;
}

void f_node_保存瓦片纹理坐标节点(C_节点基类* n, FILE* f) {
	C_瓦片纹理坐标节点* node = dynamic_cast<C_瓦片纹理坐标节点*>(n);
}






